| 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 30 matching lines...) Expand all Loading... |
| 41 #include "hydrogen-dce.h" | 41 #include "hydrogen-dce.h" |
| 42 #include "hydrogen-dehoist.h" | 42 #include "hydrogen-dehoist.h" |
| 43 #include "hydrogen-environment-liveness.h" | 43 #include "hydrogen-environment-liveness.h" |
| 44 #include "hydrogen-escape-analysis.h" | 44 #include "hydrogen-escape-analysis.h" |
| 45 #include "hydrogen-infer-representation.h" | 45 #include "hydrogen-infer-representation.h" |
| 46 #include "hydrogen-infer-types.h" | 46 #include "hydrogen-infer-types.h" |
| 47 #include "hydrogen-load-elimination.h" | 47 #include "hydrogen-load-elimination.h" |
| 48 #include "hydrogen-gvn.h" | 48 #include "hydrogen-gvn.h" |
| 49 #include "hydrogen-mark-deoptimize.h" | 49 #include "hydrogen-mark-deoptimize.h" |
| 50 #include "hydrogen-mark-unreachable.h" | 50 #include "hydrogen-mark-unreachable.h" |
| 51 #include "hydrogen-minus-zero.h" | |
| 52 #include "hydrogen-osr.h" | 51 #include "hydrogen-osr.h" |
| 53 #include "hydrogen-range-analysis.h" | 52 #include "hydrogen-range-analysis.h" |
| 54 #include "hydrogen-redundant-phi.h" | 53 #include "hydrogen-redundant-phi.h" |
| 55 #include "hydrogen-removable-simulates.h" | 54 #include "hydrogen-removable-simulates.h" |
| 56 #include "hydrogen-representation-changes.h" | 55 #include "hydrogen-representation-changes.h" |
| 57 #include "hydrogen-sce.h" | 56 #include "hydrogen-sce.h" |
| 58 #include "hydrogen-uint32-analysis.h" | 57 #include "hydrogen-uint32-analysis.h" |
| 59 #include "lithium-allocator.h" | 58 #include "lithium-allocator.h" |
| 60 #include "parser.h" | 59 #include "parser.h" |
| 61 #include "runtime.h" | 60 #include "runtime.h" |
| (...skipping 639 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 701 } | 700 } |
| 702 | 701 |
| 703 | 702 |
| 704 #define DEFINE_GET_CONSTANT(Name, name, htype, boolean_value) \ | 703 #define DEFINE_GET_CONSTANT(Name, name, htype, boolean_value) \ |
| 705 HConstant* HGraph::GetConstant##Name() { \ | 704 HConstant* HGraph::GetConstant##Name() { \ |
| 706 if (!constant_##name##_.is_set()) { \ | 705 if (!constant_##name##_.is_set()) { \ |
| 707 HConstant* constant = new(zone()) HConstant( \ | 706 HConstant* constant = new(zone()) HConstant( \ |
| 708 Unique<Object>::CreateImmovable(isolate()->factory()->name##_value()), \ | 707 Unique<Object>::CreateImmovable(isolate()->factory()->name##_value()), \ |
| 709 Representation::Tagged(), \ | 708 Representation::Tagged(), \ |
| 710 htype, \ | 709 htype, \ |
| 710 true, \ |
| 711 boolean_value, \ |
| 711 false, \ | 712 false, \ |
| 712 true, \ | 713 ODDBALL_TYPE); \ |
| 713 false, \ | |
| 714 boolean_value); \ | |
| 715 constant->InsertAfter(entry_block()->first()); \ | 714 constant->InsertAfter(entry_block()->first()); \ |
| 716 constant_##name##_.set(constant); \ | 715 constant_##name##_.set(constant); \ |
| 717 } \ | 716 } \ |
| 718 return ReinsertConstantIfNecessary(constant_##name##_.get()); \ | 717 return ReinsertConstantIfNecessary(constant_##name##_.get()); \ |
| 719 } | 718 } |
| 720 | 719 |
| 721 | 720 |
| 722 DEFINE_GET_CONSTANT(Undefined, undefined, HType::Tagged(), false) | 721 DEFINE_GET_CONSTANT(Undefined, undefined, HType::Tagged(), false) |
| 723 DEFINE_GET_CONSTANT(True, true, HType::Boolean(), true) | 722 DEFINE_GET_CONSTANT(True, true, HType::Boolean(), true) |
| 724 DEFINE_GET_CONSTANT(False, false, HType::Boolean(), false) | 723 DEFINE_GET_CONSTANT(False, false, HType::Boolean(), false) |
| (...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1276 } | 1275 } |
| 1277 | 1276 |
| 1278 | 1277 |
| 1279 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) { | 1278 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) { |
| 1280 if (object->type().IsJSObject()) return object; | 1279 if (object->type().IsJSObject()) return object; |
| 1281 if (function->IsConstant() && | 1280 if (function->IsConstant() && |
| 1282 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { | 1281 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { |
| 1283 Handle<JSFunction> f = Handle<JSFunction>::cast( | 1282 Handle<JSFunction> f = Handle<JSFunction>::cast( |
| 1284 HConstant::cast(function)->handle(isolate())); | 1283 HConstant::cast(function)->handle(isolate())); |
| 1285 SharedFunctionInfo* shared = f->shared(); | 1284 SharedFunctionInfo* shared = f->shared(); |
| 1286 if (!shared->is_classic_mode() || shared->native()) return object; | 1285 if (shared->strict_mode() == STRICT || shared->native()) return object; |
| 1287 } | 1286 } |
| 1288 return Add<HWrapReceiver>(object, function); | 1287 return Add<HWrapReceiver>(object, function); |
| 1289 } | 1288 } |
| 1290 | 1289 |
| 1291 | 1290 |
| 1292 HValue* HGraphBuilder::BuildCheckForCapacityGrow( | 1291 HValue* HGraphBuilder::BuildCheckForCapacityGrow( |
| 1293 HValue* object, | 1292 HValue* object, |
| 1294 HValue* elements, | 1293 HValue* elements, |
| 1295 ElementsKind kind, | 1294 ElementsKind kind, |
| 1296 HValue* length, | 1295 HValue* length, |
| (...skipping 2588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3885 } | 3884 } |
| 3886 | 3885 |
| 3887 | 3886 |
| 3888 void HOptimizedGraphBuilder::VisitForTypeOf(Expression* expr) { | 3887 void HOptimizedGraphBuilder::VisitForTypeOf(Expression* expr) { |
| 3889 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); | 3888 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); |
| 3890 for_value.set_for_typeof(true); | 3889 for_value.set_for_typeof(true); |
| 3891 Visit(expr); | 3890 Visit(expr); |
| 3892 } | 3891 } |
| 3893 | 3892 |
| 3894 | 3893 |
| 3895 | |
| 3896 void HOptimizedGraphBuilder::VisitForControl(Expression* expr, | 3894 void HOptimizedGraphBuilder::VisitForControl(Expression* expr, |
| 3897 HBasicBlock* true_block, | 3895 HBasicBlock* true_block, |
| 3898 HBasicBlock* false_block) { | 3896 HBasicBlock* false_block) { |
| 3899 TestContext for_test(this, expr, true_block, false_block); | 3897 TestContext for_test(this, expr, true_block, false_block); |
| 3900 Visit(expr); | 3898 Visit(expr); |
| 3901 } | 3899 } |
| 3902 | 3900 |
| 3903 | 3901 |
| 3904 void HOptimizedGraphBuilder::VisitArgument(Expression* expr) { | |
| 3905 CHECK_ALIVE(VisitForValue(expr)); | |
| 3906 Push(Add<HPushArgument>(Pop())); | |
| 3907 } | |
| 3908 | |
| 3909 | |
| 3910 void HOptimizedGraphBuilder::VisitArgumentList( | |
| 3911 ZoneList<Expression*>* arguments) { | |
| 3912 for (int i = 0; i < arguments->length(); i++) { | |
| 3913 CHECK_ALIVE(VisitArgument(arguments->at(i))); | |
| 3914 } | |
| 3915 } | |
| 3916 | |
| 3917 | |
| 3918 void HOptimizedGraphBuilder::VisitExpressions( | 3902 void HOptimizedGraphBuilder::VisitExpressions( |
| 3919 ZoneList<Expression*>* exprs) { | 3903 ZoneList<Expression*>* exprs) { |
| 3920 for (int i = 0; i < exprs->length(); ++i) { | 3904 for (int i = 0; i < exprs->length(); ++i) { |
| 3921 CHECK_ALIVE(VisitForValue(exprs->at(i))); | 3905 CHECK_ALIVE(VisitForValue(exprs->at(i))); |
| 3922 } | 3906 } |
| 3923 } | 3907 } |
| 3924 | 3908 |
| 3925 | 3909 |
| 3926 bool HOptimizedGraphBuilder::BuildGraph() { | 3910 bool HOptimizedGraphBuilder::BuildGraph() { |
| 3927 if (current_info()->function()->is_generator()) { | 3911 if (current_info()->function()->is_generator()) { |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4057 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with | 4041 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with |
| 4058 // zero. | 4042 // zero. |
| 4059 if (FLAG_opt_safe_uint32_operations) Run<HUint32AnalysisPhase>(); | 4043 if (FLAG_opt_safe_uint32_operations) Run<HUint32AnalysisPhase>(); |
| 4060 | 4044 |
| 4061 if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>(); | 4045 if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>(); |
| 4062 | 4046 |
| 4063 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>(); | 4047 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>(); |
| 4064 | 4048 |
| 4065 if (FLAG_check_elimination) Run<HCheckEliminationPhase>(); | 4049 if (FLAG_check_elimination) Run<HCheckEliminationPhase>(); |
| 4066 | 4050 |
| 4067 if (FLAG_use_range) Run<HRangeAnalysisPhase>(); | 4051 Run<HRangeAnalysisPhase>(); |
| 4068 | 4052 |
| 4069 Run<HComputeChangeUndefinedToNaN>(); | 4053 Run<HComputeChangeUndefinedToNaN>(); |
| 4070 Run<HComputeMinusZeroChecksPhase>(); | |
| 4071 | 4054 |
| 4072 // Eliminate redundant stack checks on backwards branches. | 4055 // Eliminate redundant stack checks on backwards branches. |
| 4073 Run<HStackCheckEliminationPhase>(); | 4056 Run<HStackCheckEliminationPhase>(); |
| 4074 | 4057 |
| 4075 if (FLAG_array_bounds_checks_elimination) Run<HBoundsCheckEliminationPhase>(); | 4058 if (FLAG_array_bounds_checks_elimination) Run<HBoundsCheckEliminationPhase>(); |
| 4076 if (FLAG_array_bounds_checks_hoisting) Run<HBoundsCheckHoistingPhase>(); | 4059 if (FLAG_array_bounds_checks_hoisting) Run<HBoundsCheckHoistingPhase>(); |
| 4077 if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>(); | 4060 if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>(); |
| 4078 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); | 4061 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); |
| 4079 | 4062 |
| 4080 RestoreActualValues(); | 4063 RestoreActualValues(); |
| (...skipping 1513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5594 builder_, access_type_, ToType(types->at(i)), name_); | 5577 builder_, access_type_, ToType(types->at(i)), name_); |
| 5595 if (!test_info.IsCompatible(this)) return false; | 5578 if (!test_info.IsCompatible(this)) return false; |
| 5596 } | 5579 } |
| 5597 | 5580 |
| 5598 return true; | 5581 return true; |
| 5599 } | 5582 } |
| 5600 | 5583 |
| 5601 | 5584 |
| 5602 static bool NeedsWrappingFor(Type* type, Handle<JSFunction> target) { | 5585 static bool NeedsWrappingFor(Type* type, Handle<JSFunction> target) { |
| 5603 return type->Is(Type::NumberOrString()) && | 5586 return type->Is(Type::NumberOrString()) && |
| 5604 target->shared()->is_classic_mode() && | 5587 target->shared()->strict_mode() == SLOPPY && |
| 5605 !target->shared()->native(); | 5588 !target->shared()->native(); |
| 5606 } | 5589 } |
| 5607 | 5590 |
| 5608 | 5591 |
| 5609 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess( | 5592 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess( |
| 5610 PropertyAccessInfo* info, | 5593 PropertyAccessInfo* info, |
| 5611 HValue* object, | 5594 HValue* object, |
| 5612 HValue* checked_object, | 5595 HValue* checked_object, |
| 5613 HValue* value, | 5596 HValue* value, |
| 5614 BailoutId ast_id, | 5597 BailoutId ast_id, |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5935 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); | 5918 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); |
| 5936 if (instr->HasObservableSideEffects()) { | 5919 if (instr->HasObservableSideEffects()) { |
| 5937 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 5920 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 5938 } | 5921 } |
| 5939 } else { | 5922 } else { |
| 5940 HValue* global_object = Add<HLoadNamedField>( | 5923 HValue* global_object = Add<HLoadNamedField>( |
| 5941 context(), static_cast<HValue*>(NULL), | 5924 context(), static_cast<HValue*>(NULL), |
| 5942 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); | 5925 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); |
| 5943 HStoreNamedGeneric* instr = | 5926 HStoreNamedGeneric* instr = |
| 5944 Add<HStoreNamedGeneric>(global_object, var->name(), | 5927 Add<HStoreNamedGeneric>(global_object, var->name(), |
| 5945 value, function_strict_mode_flag()); | 5928 value, function_strict_mode()); |
| 5946 USE(instr); | 5929 USE(instr); |
| 5947 ASSERT(instr->HasObservableSideEffects()); | 5930 ASSERT(instr->HasObservableSideEffects()); |
| 5948 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 5931 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 5949 } | 5932 } |
| 5950 } | 5933 } |
| 5951 | 5934 |
| 5952 | 5935 |
| 5953 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 5936 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
| 5954 Expression* target = expr->target(); | 5937 Expression* target = expr->target(); |
| 5955 VariableProxy* proxy = target->AsVariableProxy(); | 5938 VariableProxy* proxy = target->AsVariableProxy(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 5970 | 5953 |
| 5971 switch (var->location()) { | 5954 switch (var->location()) { |
| 5972 case Variable::UNALLOCATED: | 5955 case Variable::UNALLOCATED: |
| 5973 HandleGlobalVariableAssignment(var, | 5956 HandleGlobalVariableAssignment(var, |
| 5974 Top(), | 5957 Top(), |
| 5975 expr->AssignmentId()); | 5958 expr->AssignmentId()); |
| 5976 break; | 5959 break; |
| 5977 | 5960 |
| 5978 case Variable::PARAMETER: | 5961 case Variable::PARAMETER: |
| 5979 case Variable::LOCAL: | 5962 case Variable::LOCAL: |
| 5980 if (var->mode() == CONST) { | 5963 if (var->mode() == CONST_LEGACY) { |
| 5981 return Bailout(kUnsupportedConstCompoundAssignment); | 5964 return Bailout(kUnsupportedConstCompoundAssignment); |
| 5982 } | 5965 } |
| 5983 BindIfLive(var, Top()); | 5966 BindIfLive(var, Top()); |
| 5984 break; | 5967 break; |
| 5985 | 5968 |
| 5986 case Variable::CONTEXT: { | 5969 case Variable::CONTEXT: { |
| 5987 // Bail out if we try to mutate a parameter value in a function | 5970 // Bail out if we try to mutate a parameter value in a function |
| 5988 // using the arguments object. We do not (yet) correctly handle the | 5971 // using the arguments object. We do not (yet) correctly handle the |
| 5989 // arguments property of the function. | 5972 // arguments property of the function. |
| 5990 if (current_info()->scope()->arguments() != NULL) { | 5973 if (current_info()->scope()->arguments() != NULL) { |
| 5991 // Parameters will be allocated to context slots. We have no | 5974 // Parameters will be allocated to context slots. We have no |
| 5992 // direct way to detect that the variable is a parameter so we do | 5975 // direct way to detect that the variable is a parameter so we do |
| 5993 // a linear search of the parameter variables. | 5976 // a linear search of the parameter variables. |
| 5994 int count = current_info()->scope()->num_parameters(); | 5977 int count = current_info()->scope()->num_parameters(); |
| 5995 for (int i = 0; i < count; ++i) { | 5978 for (int i = 0; i < count; ++i) { |
| 5996 if (var == current_info()->scope()->parameter(i)) { | 5979 if (var == current_info()->scope()->parameter(i)) { |
| 5997 Bailout(kAssignmentToParameterFunctionUsesArgumentsObject); | 5980 Bailout(kAssignmentToParameterFunctionUsesArgumentsObject); |
| 5998 } | 5981 } |
| 5999 } | 5982 } |
| 6000 } | 5983 } |
| 6001 | 5984 |
| 6002 HStoreContextSlot::Mode mode; | 5985 HStoreContextSlot::Mode mode; |
| 6003 | 5986 |
| 6004 switch (var->mode()) { | 5987 switch (var->mode()) { |
| 6005 case LET: | 5988 case LET: |
| 6006 mode = HStoreContextSlot::kCheckDeoptimize; | 5989 mode = HStoreContextSlot::kCheckDeoptimize; |
| 6007 break; | 5990 break; |
| 6008 case CONST: | 5991 case CONST: |
| 6009 return ast_context()->ReturnValue(Pop()); | |
| 6010 case CONST_HARMONY: | |
| 6011 // This case is checked statically so no need to | 5992 // This case is checked statically so no need to |
| 6012 // perform checks here | 5993 // perform checks here |
| 6013 UNREACHABLE(); | 5994 UNREACHABLE(); |
| 5995 case CONST_LEGACY: |
| 5996 return ast_context()->ReturnValue(Pop()); |
| 6014 default: | 5997 default: |
| 6015 mode = HStoreContextSlot::kNoCheck; | 5998 mode = HStoreContextSlot::kNoCheck; |
| 6016 } | 5999 } |
| 6017 | 6000 |
| 6018 HValue* context = BuildContextChainWalk(var); | 6001 HValue* context = BuildContextChainWalk(var); |
| 6019 HStoreContextSlot* instr = Add<HStoreContextSlot>( | 6002 HStoreContextSlot* instr = Add<HStoreContextSlot>( |
| 6020 context, var->index(), mode, Top()); | 6003 context, var->index(), mode, Top()); |
| 6021 if (instr->HasObservableSideEffects()) { | 6004 if (instr->HasObservableSideEffects()) { |
| 6022 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); | 6005 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 6023 } | 6006 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6068 return; | 6051 return; |
| 6069 } | 6052 } |
| 6070 | 6053 |
| 6071 if (prop != NULL) { | 6054 if (prop != NULL) { |
| 6072 HandlePropertyAssignment(expr); | 6055 HandlePropertyAssignment(expr); |
| 6073 } else if (proxy != NULL) { | 6056 } else if (proxy != NULL) { |
| 6074 Variable* var = proxy->var(); | 6057 Variable* var = proxy->var(); |
| 6075 | 6058 |
| 6076 if (var->mode() == CONST) { | 6059 if (var->mode() == CONST) { |
| 6077 if (expr->op() != Token::INIT_CONST) { | 6060 if (expr->op() != Token::INIT_CONST) { |
| 6061 return Bailout(kNonInitializerAssignmentToConst); |
| 6062 } |
| 6063 } else if (var->mode() == CONST_LEGACY) { |
| 6064 if (expr->op() != Token::INIT_CONST_LEGACY) { |
| 6078 CHECK_ALIVE(VisitForValue(expr->value())); | 6065 CHECK_ALIVE(VisitForValue(expr->value())); |
| 6079 return ast_context()->ReturnValue(Pop()); | 6066 return ast_context()->ReturnValue(Pop()); |
| 6080 } | 6067 } |
| 6081 | 6068 |
| 6082 if (var->IsStackAllocated()) { | 6069 if (var->IsStackAllocated()) { |
| 6083 // We insert a use of the old value to detect unsupported uses of const | 6070 // We insert a use of the old value to detect unsupported uses of const |
| 6084 // variables (e.g. initialization inside a loop). | 6071 // variables (e.g. initialization inside a loop). |
| 6085 HValue* old_value = environment()->Lookup(var); | 6072 HValue* old_value = environment()->Lookup(var); |
| 6086 Add<HUseConst>(old_value); | 6073 Add<HUseConst>(old_value); |
| 6087 } | 6074 } |
| 6088 } else if (var->mode() == CONST_HARMONY) { | |
| 6089 if (expr->op() != Token::INIT_CONST_HARMONY) { | |
| 6090 return Bailout(kNonInitializerAssignmentToConst); | |
| 6091 } | |
| 6092 } | 6075 } |
| 6093 | 6076 |
| 6094 if (proxy->IsArguments()) return Bailout(kAssignmentToArguments); | 6077 if (proxy->IsArguments()) return Bailout(kAssignmentToArguments); |
| 6095 | 6078 |
| 6096 // Handle the assignment. | 6079 // Handle the assignment. |
| 6097 switch (var->location()) { | 6080 switch (var->location()) { |
| 6098 case Variable::UNALLOCATED: | 6081 case Variable::UNALLOCATED: |
| 6099 CHECK_ALIVE(VisitForValue(expr->value())); | 6082 CHECK_ALIVE(VisitForValue(expr->value())); |
| 6100 HandleGlobalVariableAssignment(var, | 6083 HandleGlobalVariableAssignment(var, |
| 6101 Top(), | 6084 Top(), |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6137 } | 6120 } |
| 6138 | 6121 |
| 6139 CHECK_ALIVE(VisitForValue(expr->value())); | 6122 CHECK_ALIVE(VisitForValue(expr->value())); |
| 6140 HStoreContextSlot::Mode mode; | 6123 HStoreContextSlot::Mode mode; |
| 6141 if (expr->op() == Token::ASSIGN) { | 6124 if (expr->op() == Token::ASSIGN) { |
| 6142 switch (var->mode()) { | 6125 switch (var->mode()) { |
| 6143 case LET: | 6126 case LET: |
| 6144 mode = HStoreContextSlot::kCheckDeoptimize; | 6127 mode = HStoreContextSlot::kCheckDeoptimize; |
| 6145 break; | 6128 break; |
| 6146 case CONST: | 6129 case CONST: |
| 6147 return ast_context()->ReturnValue(Pop()); | |
| 6148 case CONST_HARMONY: | |
| 6149 // This case is checked statically so no need to | 6130 // This case is checked statically so no need to |
| 6150 // perform checks here | 6131 // perform checks here |
| 6151 UNREACHABLE(); | 6132 UNREACHABLE(); |
| 6133 case CONST_LEGACY: |
| 6134 return ast_context()->ReturnValue(Pop()); |
| 6152 default: | 6135 default: |
| 6153 mode = HStoreContextSlot::kNoCheck; | 6136 mode = HStoreContextSlot::kNoCheck; |
| 6154 } | 6137 } |
| 6155 } else if (expr->op() == Token::INIT_VAR || | 6138 } else if (expr->op() == Token::INIT_VAR || |
| 6156 expr->op() == Token::INIT_LET || | 6139 expr->op() == Token::INIT_LET || |
| 6157 expr->op() == Token::INIT_CONST_HARMONY) { | 6140 expr->op() == Token::INIT_CONST) { |
| 6158 mode = HStoreContextSlot::kNoCheck; | 6141 mode = HStoreContextSlot::kNoCheck; |
| 6159 } else { | 6142 } else { |
| 6160 ASSERT(expr->op() == Token::INIT_CONST); | 6143 ASSERT(expr->op() == Token::INIT_CONST_LEGACY); |
| 6161 | 6144 |
| 6162 mode = HStoreContextSlot::kCheckIgnoreAssignment; | 6145 mode = HStoreContextSlot::kCheckIgnoreAssignment; |
| 6163 } | 6146 } |
| 6164 | 6147 |
| 6165 HValue* context = BuildContextChainWalk(var); | 6148 HValue* context = BuildContextChainWalk(var); |
| 6166 HStoreContextSlot* instr = Add<HStoreContextSlot>( | 6149 HStoreContextSlot* instr = Add<HStoreContextSlot>( |
| 6167 context, var->index(), mode, Top()); | 6150 context, var->index(), mode, Top()); |
| 6168 if (instr->HasObservableSideEffects()) { | 6151 if (instr->HasObservableSideEffects()) { |
| 6169 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); | 6152 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
| 6170 } | 6153 } |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6244 Handle<String> name, | 6227 Handle<String> name, |
| 6245 HValue* value, | 6228 HValue* value, |
| 6246 bool is_uninitialized) { | 6229 bool is_uninitialized) { |
| 6247 if (is_uninitialized) { | 6230 if (is_uninitialized) { |
| 6248 Add<HDeoptimize>("Insufficient type feedback for generic named access", | 6231 Add<HDeoptimize>("Insufficient type feedback for generic named access", |
| 6249 Deoptimizer::SOFT); | 6232 Deoptimizer::SOFT); |
| 6250 } | 6233 } |
| 6251 if (access_type == LOAD) { | 6234 if (access_type == LOAD) { |
| 6252 return New<HLoadNamedGeneric>(object, name); | 6235 return New<HLoadNamedGeneric>(object, name); |
| 6253 } else { | 6236 } else { |
| 6254 return New<HStoreNamedGeneric>( | 6237 return New<HStoreNamedGeneric>(object, name, value, function_strict_mode()); |
| 6255 object, name, value, function_strict_mode_flag()); | |
| 6256 } | 6238 } |
| 6257 } | 6239 } |
| 6258 | 6240 |
| 6259 | 6241 |
| 6260 | 6242 |
| 6261 HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric( | 6243 HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric( |
| 6262 PropertyAccessType access_type, | 6244 PropertyAccessType access_type, |
| 6263 HValue* object, | 6245 HValue* object, |
| 6264 HValue* key, | 6246 HValue* key, |
| 6265 HValue* value) { | 6247 HValue* value) { |
| 6266 if (access_type == LOAD) { | 6248 if (access_type == LOAD) { |
| 6267 return New<HLoadKeyedGeneric>(object, key); | 6249 return New<HLoadKeyedGeneric>(object, key); |
| 6268 } else { | 6250 } else { |
| 6269 return New<HStoreKeyedGeneric>( | 6251 return New<HStoreKeyedGeneric>(object, key, value, function_strict_mode()); |
| 6270 object, key, value, function_strict_mode_flag()); | |
| 6271 } | 6252 } |
| 6272 } | 6253 } |
| 6273 | 6254 |
| 6274 | 6255 |
| 6275 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) { | 6256 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) { |
| 6276 // Loads from a "stock" fast holey double arrays can elide the hole check. | 6257 // Loads from a "stock" fast holey double arrays can elide the hole check. |
| 6277 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; | 6258 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; |
| 6278 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && | 6259 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && |
| 6279 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { | 6260 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { |
| 6280 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); | 6261 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); |
| (...skipping 937 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7218 return false; | 7199 return false; |
| 7219 } | 7200 } |
| 7220 if (target_shared->scope_info() == ScopeInfo::Empty(isolate())) { | 7201 if (target_shared->scope_info() == ScopeInfo::Empty(isolate())) { |
| 7221 // The scope info might not have been set if a lazily compiled | 7202 // The scope info might not have been set if a lazily compiled |
| 7222 // function is inlined before being called for the first time. | 7203 // function is inlined before being called for the first time. |
| 7223 Handle<ScopeInfo> target_scope_info = | 7204 Handle<ScopeInfo> target_scope_info = |
| 7224 ScopeInfo::Create(target_info.scope(), zone()); | 7205 ScopeInfo::Create(target_info.scope(), zone()); |
| 7225 target_shared->set_scope_info(*target_scope_info); | 7206 target_shared->set_scope_info(*target_scope_info); |
| 7226 } | 7207 } |
| 7227 target_shared->EnableDeoptimizationSupport(*target_info.code()); | 7208 target_shared->EnableDeoptimizationSupport(*target_info.code()); |
| 7209 target_shared->set_feedback_vector(*target_info.feedback_vector()); |
| 7228 Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG, | 7210 Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG, |
| 7229 &target_info, | 7211 &target_info, |
| 7230 target_shared); | 7212 target_shared); |
| 7231 } | 7213 } |
| 7232 | 7214 |
| 7233 // ---------------------------------------------------------------- | 7215 // ---------------------------------------------------------------- |
| 7234 // After this point, we've made a decision to inline this function (so | 7216 // After this point, we've made a decision to inline this function (so |
| 7235 // TryInline should always return true). | 7217 // TryInline should always return true). |
| 7236 | 7218 |
| 7237 // Type-check the inlined function. | 7219 // Type-check the inlined function. |
| (...skipping 708 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7946 Drop(1); // Function. | 7928 Drop(1); // Function. |
| 7947 ast_context()->ReturnInstruction(call, expr->id()); | 7929 ast_context()->ReturnInstruction(call, expr->id()); |
| 7948 return true; | 7930 return true; |
| 7949 } | 7931 } |
| 7950 } | 7932 } |
| 7951 | 7933 |
| 7952 | 7934 |
| 7953 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function, | 7935 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function, |
| 7954 Handle<JSFunction> target) { | 7936 Handle<JSFunction> target) { |
| 7955 SharedFunctionInfo* shared = target->shared(); | 7937 SharedFunctionInfo* shared = target->shared(); |
| 7956 if (shared->is_classic_mode() && !shared->native()) { | 7938 if (shared->strict_mode() == SLOPPY && !shared->native()) { |
| 7957 // Cannot embed a direct reference to the global proxy | 7939 // Cannot embed a direct reference to the global proxy |
| 7958 // as is it dropped on deserialization. | 7940 // as is it dropped on deserialization. |
| 7959 CHECK(!Serializer::enabled()); | 7941 CHECK(!Serializer::enabled()); |
| 7960 Handle<JSObject> global_receiver( | 7942 Handle<JSObject> global_receiver( |
| 7961 target->context()->global_object()->global_receiver()); | 7943 target->context()->global_object()->global_receiver()); |
| 7962 return Add<HConstant>(global_receiver); | 7944 return Add<HConstant>(global_receiver); |
| 7963 } | 7945 } |
| 7964 return graph()->GetConstantUndefined(); | 7946 return graph()->GetConstantUndefined(); |
| 7965 } | 7947 } |
| 7966 | 7948 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8048 call = New<HCallFunction>(function, argument_count, flags); | 8030 call = New<HCallFunction>(function, argument_count, flags); |
| 8049 } | 8031 } |
| 8050 PushArgumentsFromEnvironment(argument_count); | 8032 PushArgumentsFromEnvironment(argument_count); |
| 8051 | 8033 |
| 8052 } else { | 8034 } else { |
| 8053 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 8035 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 8054 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { | 8036 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { |
| 8055 return Bailout(kPossibleDirectCallToEval); | 8037 return Bailout(kPossibleDirectCallToEval); |
| 8056 } | 8038 } |
| 8057 | 8039 |
| 8040 // The function is on the stack in the unoptimized code during |
| 8041 // evaluation of the arguments. |
| 8042 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 8043 HValue* function = Top(); |
| 8058 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); | 8044 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); |
| 8059 if (global_call) { | 8045 if (global_call) { |
| 8060 Variable* var = proxy->var(); | 8046 Variable* var = proxy->var(); |
| 8061 bool known_global_function = false; | 8047 bool known_global_function = false; |
| 8062 // If there is a global property cell for the name at compile time and | 8048 // If there is a global property cell for the name at compile time and |
| 8063 // access check is not enabled we assume that the function will not change | 8049 // access check is not enabled we assume that the function will not change |
| 8064 // and generate optimized code for calling the function. | 8050 // and generate optimized code for calling the function. |
| 8065 LookupResult lookup(isolate()); | 8051 LookupResult lookup(isolate()); |
| 8066 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, LOAD); | 8052 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, LOAD); |
| 8067 if (type == kUseCell && | 8053 if (type == kUseCell && |
| 8068 !current_info()->global_object()->IsAccessCheckNeeded()) { | 8054 !current_info()->global_object()->IsAccessCheckNeeded()) { |
| 8069 Handle<GlobalObject> global(current_info()->global_object()); | 8055 Handle<GlobalObject> global(current_info()->global_object()); |
| 8070 known_global_function = expr->ComputeGlobalTarget(global, &lookup); | 8056 known_global_function = expr->ComputeGlobalTarget(global, &lookup); |
| 8071 } | 8057 } |
| 8072 CHECK_ALIVE(VisitForValue(expr->expression())); | |
| 8073 HValue* function = Top(); | |
| 8074 if (known_global_function) { | 8058 if (known_global_function) { |
| 8075 Add<HCheckValue>(function, expr->target()); | 8059 Add<HCheckValue>(function, expr->target()); |
| 8076 | 8060 |
| 8077 // Placeholder for the receiver. | 8061 // Placeholder for the receiver. |
| 8078 Push(graph()->GetConstantUndefined()); | 8062 Push(graph()->GetConstantUndefined()); |
| 8079 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 8063 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 8080 | 8064 |
| 8081 // Patch the global object on the stack by the expected receiver. | 8065 // Patch the global object on the stack by the expected receiver. |
| 8082 HValue* receiver = ImplicitReceiverFor(function, expr->target()); | 8066 HValue* receiver = ImplicitReceiverFor(function, expr->target()); |
| 8083 const int receiver_index = argument_count - 1; | 8067 const int receiver_index = argument_count - 1; |
| 8084 environment()->SetExpressionStackAt(receiver_index, receiver); | 8068 environment()->SetExpressionStackAt(receiver_index, receiver); |
| 8085 | 8069 |
| 8086 if (TryInlineBuiltinFunctionCall(expr)) { | 8070 if (TryInlineBuiltinFunctionCall(expr)) { |
| 8087 if (FLAG_trace_inlining) { | 8071 if (FLAG_trace_inlining) { |
| 8088 PrintF("Inlining builtin "); | 8072 PrintF("Inlining builtin "); |
| 8089 expr->target()->ShortPrint(); | 8073 expr->target()->ShortPrint(); |
| 8090 PrintF("\n"); | 8074 PrintF("\n"); |
| 8091 } | 8075 } |
| 8092 return; | 8076 return; |
| 8093 } | 8077 } |
| 8094 if (TryInlineApiFunctionCall(expr, receiver)) return; | 8078 if (TryInlineApiFunctionCall(expr, receiver)) return; |
| 8095 if (TryInlineCall(expr)) return; | 8079 if (TryInlineCall(expr)) return; |
| 8096 | 8080 |
| 8097 PushArgumentsFromEnvironment(argument_count); | 8081 PushArgumentsFromEnvironment(argument_count); |
| 8098 call = BuildCallConstantFunction(expr->target(), argument_count); | 8082 call = BuildCallConstantFunction(expr->target(), argument_count); |
| 8099 } else { | 8083 } else { |
| 8100 Push(Add<HPushArgument>(graph()->GetConstantUndefined())); | 8084 Push(graph()->GetConstantUndefined()); |
| 8101 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 8085 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 8086 PushArgumentsFromEnvironment(argument_count); |
| 8102 call = New<HCallFunction>(function, argument_count); | 8087 call = New<HCallFunction>(function, argument_count); |
| 8103 Drop(argument_count); | |
| 8104 } | 8088 } |
| 8105 | 8089 |
| 8106 } else if (expr->IsMonomorphic()) { | 8090 } else if (expr->IsMonomorphic()) { |
| 8107 // The function is on the stack in the unoptimized code during | |
| 8108 // evaluation of the arguments. | |
| 8109 CHECK_ALIVE(VisitForValue(expr->expression())); | |
| 8110 HValue* function = Top(); | |
| 8111 | |
| 8112 Add<HCheckValue>(function, expr->target()); | 8091 Add<HCheckValue>(function, expr->target()); |
| 8113 | 8092 |
| 8114 Push(graph()->GetConstantUndefined()); | 8093 Push(graph()->GetConstantUndefined()); |
| 8115 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 8094 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 8116 | 8095 |
| 8117 HValue* receiver = ImplicitReceiverFor(function, expr->target()); | 8096 HValue* receiver = ImplicitReceiverFor(function, expr->target()); |
| 8118 const int receiver_index = argument_count - 1; | 8097 const int receiver_index = argument_count - 1; |
| 8119 environment()->SetExpressionStackAt(receiver_index, receiver); | 8098 environment()->SetExpressionStackAt(receiver_index, receiver); |
| 8120 | 8099 |
| 8121 if (TryInlineBuiltinFunctionCall(expr)) { | 8100 if (TryInlineBuiltinFunctionCall(expr)) { |
| 8122 if (FLAG_trace_inlining) { | 8101 if (FLAG_trace_inlining) { |
| 8123 PrintF("Inlining builtin "); | 8102 PrintF("Inlining builtin "); |
| 8124 expr->target()->ShortPrint(); | 8103 expr->target()->ShortPrint(); |
| 8125 PrintF("\n"); | 8104 PrintF("\n"); |
| 8126 } | 8105 } |
| 8127 return; | 8106 return; |
| 8128 } | 8107 } |
| 8129 if (TryInlineApiFunctionCall(expr, receiver)) return; | 8108 if (TryInlineApiFunctionCall(expr, receiver)) return; |
| 8130 | 8109 |
| 8131 if (TryInlineCall(expr)) return; | 8110 if (TryInlineCall(expr)) return; |
| 8132 | 8111 |
| 8133 call = PreProcessCall(New<HInvokeFunction>( | 8112 call = PreProcessCall(New<HInvokeFunction>( |
| 8134 function, expr->target(), argument_count)); | 8113 function, expr->target(), argument_count)); |
| 8135 | 8114 |
| 8136 } else { | 8115 } else { |
| 8137 CHECK_ALIVE(VisitForValue(expr->expression())); | 8116 Push(graph()->GetConstantUndefined()); |
| 8138 HValue* function = Top(); | 8117 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 8139 HValue* receiver = graph()->GetConstantUndefined(); | 8118 PushArgumentsFromEnvironment(argument_count); |
| 8140 Push(Add<HPushArgument>(receiver)); | |
| 8141 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | |
| 8142 call = New<HCallFunction>(function, argument_count); | 8119 call = New<HCallFunction>(function, argument_count); |
| 8143 Drop(argument_count); | |
| 8144 } | 8120 } |
| 8145 } | 8121 } |
| 8146 | 8122 |
| 8147 Drop(1); // Drop the function. | 8123 Drop(1); // Drop the function. |
| 8148 return ast_context()->ReturnInstruction(call, expr->id()); | 8124 return ast_context()->ReturnInstruction(call, expr->id()); |
| 8149 } | 8125 } |
| 8150 | 8126 |
| 8151 | 8127 |
| 8152 void HOptimizedGraphBuilder::BuildInlinedCallNewArray(CallNew* expr) { | 8128 void HOptimizedGraphBuilder::BuildInlinedCallNewArray(CallNew* expr) { |
| 8153 NoObservableSideEffectsScope no_effects(this); | 8129 NoObservableSideEffectsScope no_effects(this); |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8401 | 8377 |
| 8402 // Lookup table for generators for runtime calls that are generated inline. | 8378 // Lookup table for generators for runtime calls that are generated inline. |
| 8403 // Elements of the table are member pointers to functions of | 8379 // Elements of the table are member pointers to functions of |
| 8404 // HOptimizedGraphBuilder. | 8380 // HOptimizedGraphBuilder. |
| 8405 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ | 8381 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ |
| 8406 &HOptimizedGraphBuilder::Generate##Name, | 8382 &HOptimizedGraphBuilder::Generate##Name, |
| 8407 | 8383 |
| 8408 const HOptimizedGraphBuilder::InlineFunctionGenerator | 8384 const HOptimizedGraphBuilder::InlineFunctionGenerator |
| 8409 HOptimizedGraphBuilder::kInlineFunctionGenerators[] = { | 8385 HOptimizedGraphBuilder::kInlineFunctionGenerators[] = { |
| 8410 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) | 8386 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) |
| 8411 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) | |
| 8412 }; | 8387 }; |
| 8413 #undef INLINE_FUNCTION_GENERATOR_ADDRESS | 8388 #undef INLINE_FUNCTION_GENERATOR_ADDRESS |
| 8414 | 8389 |
| 8415 | 8390 |
| 8416 template <class ViewClass> | 8391 template <class ViewClass> |
| 8417 void HGraphBuilder::BuildArrayBufferViewInitialization( | 8392 void HGraphBuilder::BuildArrayBufferViewInitialization( |
| 8418 HValue* obj, | 8393 HValue* obj, |
| 8419 HValue* buffer, | 8394 HValue* buffer, |
| 8420 HValue* byte_offset, | 8395 HValue* byte_offset, |
| 8421 HValue* byte_length) { | 8396 HValue* byte_length) { |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8573 Add<HStoreNamedField>(elements, | 8548 Add<HStoreNamedField>(elements, |
| 8574 HObjectAccess::ForFixedArrayLength(), | 8549 HObjectAccess::ForFixedArrayLength(), |
| 8575 length); | 8550 length); |
| 8576 Add<HStoreNamedField>( | 8551 Add<HStoreNamedField>( |
| 8577 obj, HObjectAccess::ForElementsPointer(), elements); | 8552 obj, HObjectAccess::ForElementsPointer(), elements); |
| 8578 } | 8553 } |
| 8579 | 8554 |
| 8580 if (!is_zero_byte_offset) { | 8555 if (!is_zero_byte_offset) { |
| 8581 byte_offset_smi.Else(); | 8556 byte_offset_smi.Else(); |
| 8582 { // byte_offset is not Smi. | 8557 { // byte_offset is not Smi. |
| 8583 Push(Add<HPushArgument>(obj)); | 8558 Push(obj); |
| 8584 VisitArgument(arguments->at(kArrayIdArg)); | 8559 CHECK_ALIVE(VisitForValue(arguments->at(kArrayIdArg))); |
| 8585 Push(Add<HPushArgument>(buffer)); | 8560 Push(buffer); |
| 8586 Push(Add<HPushArgument>(byte_offset)); | 8561 Push(byte_offset); |
| 8587 Push(Add<HPushArgument>(byte_length)); | 8562 Push(byte_length); |
| 8563 PushArgumentsFromEnvironment(kArgsLength); |
| 8588 Add<HCallRuntime>(expr->name(), expr->function(), kArgsLength); | 8564 Add<HCallRuntime>(expr->name(), expr->function(), kArgsLength); |
| 8589 Drop(kArgsLength); | |
| 8590 } | 8565 } |
| 8591 } | 8566 } |
| 8592 byte_offset_smi.End(); | 8567 byte_offset_smi.End(); |
| 8593 } | 8568 } |
| 8594 | 8569 |
| 8595 | 8570 |
| 8596 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { | 8571 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
| 8597 ASSERT(!HasStackOverflow()); | 8572 ASSERT(!HasStackOverflow()); |
| 8598 ASSERT(current_block() != NULL); | 8573 ASSERT(current_block() != NULL); |
| 8599 ASSERT(current_block()->HasPredecessor()); | 8574 ASSERT(current_block()->HasPredecessor()); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 8626 static_cast<int>(Runtime::kFirstInlineFunction); | 8601 static_cast<int>(Runtime::kFirstInlineFunction); |
| 8627 ASSERT(lookup_index >= 0); | 8602 ASSERT(lookup_index >= 0); |
| 8628 ASSERT(static_cast<size_t>(lookup_index) < | 8603 ASSERT(static_cast<size_t>(lookup_index) < |
| 8629 ARRAY_SIZE(kInlineFunctionGenerators)); | 8604 ARRAY_SIZE(kInlineFunctionGenerators)); |
| 8630 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; | 8605 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; |
| 8631 | 8606 |
| 8632 // Call the inline code generator using the pointer-to-member. | 8607 // Call the inline code generator using the pointer-to-member. |
| 8633 (this->*generator)(expr); | 8608 (this->*generator)(expr); |
| 8634 } else { | 8609 } else { |
| 8635 ASSERT(function->intrinsic_type == Runtime::RUNTIME); | 8610 ASSERT(function->intrinsic_type == Runtime::RUNTIME); |
| 8636 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | |
| 8637 | |
| 8638 Handle<String> name = expr->name(); | 8611 Handle<String> name = expr->name(); |
| 8639 int argument_count = expr->arguments()->length(); | 8612 int argument_count = expr->arguments()->length(); |
| 8613 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 8614 PushArgumentsFromEnvironment(argument_count); |
| 8640 HCallRuntime* call = New<HCallRuntime>(name, function, | 8615 HCallRuntime* call = New<HCallRuntime>(name, function, |
| 8641 argument_count); | 8616 argument_count); |
| 8642 Drop(argument_count); | |
| 8643 return ast_context()->ReturnInstruction(call, expr->id()); | 8617 return ast_context()->ReturnInstruction(call, expr->id()); |
| 8644 } | 8618 } |
| 8645 } | 8619 } |
| 8646 | 8620 |
| 8647 | 8621 |
| 8648 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { | 8622 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
| 8649 ASSERT(!HasStackOverflow()); | 8623 ASSERT(!HasStackOverflow()); |
| 8650 ASSERT(current_block() != NULL); | 8624 ASSERT(current_block() != NULL); |
| 8651 ASSERT(current_block()->HasPredecessor()); | 8625 ASSERT(current_block()->HasPredecessor()); |
| 8652 switch (expr->op()) { | 8626 switch (expr->op()) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 8663 Property* prop = expr->expression()->AsProperty(); | 8637 Property* prop = expr->expression()->AsProperty(); |
| 8664 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 8638 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 8665 if (prop != NULL) { | 8639 if (prop != NULL) { |
| 8666 CHECK_ALIVE(VisitForValue(prop->obj())); | 8640 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 8667 CHECK_ALIVE(VisitForValue(prop->key())); | 8641 CHECK_ALIVE(VisitForValue(prop->key())); |
| 8668 HValue* key = Pop(); | 8642 HValue* key = Pop(); |
| 8669 HValue* obj = Pop(); | 8643 HValue* obj = Pop(); |
| 8670 HValue* function = AddLoadJSBuiltin(Builtins::DELETE); | 8644 HValue* function = AddLoadJSBuiltin(Builtins::DELETE); |
| 8671 Add<HPushArgument>(obj); | 8645 Add<HPushArgument>(obj); |
| 8672 Add<HPushArgument>(key); | 8646 Add<HPushArgument>(key); |
| 8673 Add<HPushArgument>(Add<HConstant>(function_strict_mode_flag())); | 8647 Add<HPushArgument>(Add<HConstant>(function_strict_mode())); |
| 8674 // TODO(olivf) InvokeFunction produces a check for the parameter count, | 8648 // TODO(olivf) InvokeFunction produces a check for the parameter count, |
| 8675 // even though we are certain to pass the correct number of arguments here. | 8649 // even though we are certain to pass the correct number of arguments here. |
| 8676 HInstruction* instr = New<HInvokeFunction>(function, 3); | 8650 HInstruction* instr = New<HInvokeFunction>(function, 3); |
| 8677 return ast_context()->ReturnInstruction(instr, expr->id()); | 8651 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 8678 } else if (proxy != NULL) { | 8652 } else if (proxy != NULL) { |
| 8679 Variable* var = proxy->var(); | 8653 Variable* var = proxy->var(); |
| 8680 if (var->IsUnallocated()) { | 8654 if (var->IsUnallocated()) { |
| 8681 Bailout(kDeleteWithGlobalVariable); | 8655 Bailout(kDeleteWithGlobalVariable); |
| 8682 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 8656 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
| 8683 // Result of deleting non-global variables is false. 'this' is not | 8657 // Result of deleting non-global variables is false. 'this' is not |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8827 // Match the full code generator stack by simulating an extra stack | 8801 // Match the full code generator stack by simulating an extra stack |
| 8828 // element for postfix operations in a non-effect context. The return | 8802 // element for postfix operations in a non-effect context. The return |
| 8829 // value is ToNumber(input). | 8803 // value is ToNumber(input). |
| 8830 bool returns_original_input = | 8804 bool returns_original_input = |
| 8831 expr->is_postfix() && !ast_context()->IsEffect(); | 8805 expr->is_postfix() && !ast_context()->IsEffect(); |
| 8832 HValue* input = NULL; // ToNumber(original_input). | 8806 HValue* input = NULL; // ToNumber(original_input). |
| 8833 HValue* after = NULL; // The result after incrementing or decrementing. | 8807 HValue* after = NULL; // The result after incrementing or decrementing. |
| 8834 | 8808 |
| 8835 if (proxy != NULL) { | 8809 if (proxy != NULL) { |
| 8836 Variable* var = proxy->var(); | 8810 Variable* var = proxy->var(); |
| 8837 if (var->mode() == CONST) { | 8811 if (var->mode() == CONST_LEGACY) { |
| 8838 return Bailout(kUnsupportedCountOperationWithConst); | 8812 return Bailout(kUnsupportedCountOperationWithConst); |
| 8839 } | 8813 } |
| 8840 // Argument of the count operation is a variable, not a property. | 8814 // Argument of the count operation is a variable, not a property. |
| 8841 ASSERT(prop == NULL); | 8815 ASSERT(prop == NULL); |
| 8842 CHECK_ALIVE(VisitForValue(target)); | 8816 CHECK_ALIVE(VisitForValue(target)); |
| 8843 | 8817 |
| 8844 after = BuildIncrement(returns_original_input, expr); | 8818 after = BuildIncrement(returns_original_input, expr); |
| 8845 input = returns_original_input ? Top() : Pop(); | 8819 input = returns_original_input ? Top() : Pop(); |
| 8846 Push(after); | 8820 Push(after); |
| 8847 | 8821 |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8951 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, | 8925 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, |
| 8952 HValue* const32_minus_sa) { | 8926 HValue* const32_minus_sa) { |
| 8953 if (sa->IsConstant() && const32_minus_sa->IsConstant()) { | 8927 if (sa->IsConstant() && const32_minus_sa->IsConstant()) { |
| 8954 const HConstant* c1 = HConstant::cast(sa); | 8928 const HConstant* c1 = HConstant::cast(sa); |
| 8955 const HConstant* c2 = HConstant::cast(const32_minus_sa); | 8929 const HConstant* c2 = HConstant::cast(const32_minus_sa); |
| 8956 return c1->HasInteger32Value() && c2->HasInteger32Value() && | 8930 return c1->HasInteger32Value() && c2->HasInteger32Value() && |
| 8957 (c1->Integer32Value() + c2->Integer32Value() == 32); | 8931 (c1->Integer32Value() + c2->Integer32Value() == 32); |
| 8958 } | 8932 } |
| 8959 if (!const32_minus_sa->IsSub()) return false; | 8933 if (!const32_minus_sa->IsSub()) return false; |
| 8960 HSub* sub = HSub::cast(const32_minus_sa); | 8934 HSub* sub = HSub::cast(const32_minus_sa); |
| 8961 if (sa != sub->right()) return false; | 8935 return sub->left()->EqualsInteger32Constant(32) && sub->right() == sa; |
| 8962 HValue* const32 = sub->left(); | |
| 8963 if (!const32->IsConstant() || | |
| 8964 HConstant::cast(const32)->Integer32Value() != 32) { | |
| 8965 return false; | |
| 8966 } | |
| 8967 return (sub->right() == sa); | |
| 8968 } | 8936 } |
| 8969 | 8937 |
| 8970 | 8938 |
| 8971 // Checks if the left and the right are shift instructions with the oposite | 8939 // Checks if the left and the right are shift instructions with the oposite |
| 8972 // directions that can be replaced by one rotate right instruction or not. | 8940 // directions that can be replaced by one rotate right instruction or not. |
| 8973 // Returns the operand and the shift amount for the rotate instruction in the | 8941 // Returns the operand and the shift amount for the rotate instruction in the |
| 8974 // former case. | 8942 // former case. |
| 8975 bool HGraphBuilder::MatchRotateRight(HValue* left, | 8943 bool HGraphBuilder::MatchRotateRight(HValue* left, |
| 8976 HValue* right, | 8944 HValue* right, |
| 8977 HValue** operand, | 8945 HValue** operand, |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9244 case Token::ADD: | 9212 case Token::ADD: |
| 9245 instr = AddUncasted<HAdd>(left, right); | 9213 instr = AddUncasted<HAdd>(left, right); |
| 9246 break; | 9214 break; |
| 9247 case Token::SUB: | 9215 case Token::SUB: |
| 9248 instr = AddUncasted<HSub>(left, right); | 9216 instr = AddUncasted<HSub>(left, right); |
| 9249 break; | 9217 break; |
| 9250 case Token::MUL: | 9218 case Token::MUL: |
| 9251 instr = AddUncasted<HMul>(left, right); | 9219 instr = AddUncasted<HMul>(left, right); |
| 9252 break; | 9220 break; |
| 9253 case Token::MOD: { | 9221 case Token::MOD: { |
| 9254 if (fixed_right_arg.has_value) { | 9222 if (fixed_right_arg.has_value && |
| 9255 if (right->IsConstant()) { | 9223 !right->EqualsInteger32Constant(fixed_right_arg.value)) { |
| 9256 HConstant* c_right = HConstant::cast(right); | 9224 HConstant* fixed_right = Add<HConstant>( |
| 9257 if (c_right->HasInteger32Value()) { | 9225 static_cast<int>(fixed_right_arg.value)); |
| 9258 ASSERT_EQ(fixed_right_arg.value, c_right->Integer32Value()); | 9226 IfBuilder if_same(this); |
| 9259 } | 9227 if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ); |
| 9260 } else { | 9228 if_same.Then(); |
| 9261 HConstant* fixed_right = Add<HConstant>( | 9229 if_same.ElseDeopt("Unexpected RHS of binary operation"); |
| 9262 static_cast<int>(fixed_right_arg.value)); | 9230 right = fixed_right; |
| 9263 IfBuilder if_same(this); | |
| 9264 if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ); | |
| 9265 if_same.Then(); | |
| 9266 if_same.ElseDeopt("Unexpected RHS of binary operation"); | |
| 9267 right = fixed_right; | |
| 9268 } | |
| 9269 } | 9231 } |
| 9270 instr = AddUncasted<HMod>(left, right); | 9232 instr = AddUncasted<HMod>(left, right); |
| 9271 break; | 9233 break; |
| 9272 } | 9234 } |
| 9273 case Token::DIV: | 9235 case Token::DIV: |
| 9274 instr = AddUncasted<HDiv>(left, right); | 9236 instr = AddUncasted<HDiv>(left, right); |
| 9275 break; | 9237 break; |
| 9276 case Token::BIT_XOR: | 9238 case Token::BIT_XOR: |
| 9277 case Token::BIT_AND: | 9239 case Token::BIT_AND: |
| 9278 instr = AddUncasted<HBitwise>(op, left, right); | 9240 instr = AddUncasted<HBitwise>(op, left, right); |
| (...skipping 758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10037 void HOptimizedGraphBuilder::VisitDeclarations( | 9999 void HOptimizedGraphBuilder::VisitDeclarations( |
| 10038 ZoneList<Declaration*>* declarations) { | 10000 ZoneList<Declaration*>* declarations) { |
| 10039 ASSERT(globals_.is_empty()); | 10001 ASSERT(globals_.is_empty()); |
| 10040 AstVisitor::VisitDeclarations(declarations); | 10002 AstVisitor::VisitDeclarations(declarations); |
| 10041 if (!globals_.is_empty()) { | 10003 if (!globals_.is_empty()) { |
| 10042 Handle<FixedArray> array = | 10004 Handle<FixedArray> array = |
| 10043 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); | 10005 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); |
| 10044 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); | 10006 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); |
| 10045 int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) | | 10007 int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) | |
| 10046 DeclareGlobalsNativeFlag::encode(current_info()->is_native()) | | 10008 DeclareGlobalsNativeFlag::encode(current_info()->is_native()) | |
| 10047 DeclareGlobalsLanguageMode::encode(current_info()->language_mode()); | 10009 DeclareGlobalsStrictMode::encode(current_info()->strict_mode()); |
| 10048 Add<HDeclareGlobals>(array, flags); | 10010 Add<HDeclareGlobals>(array, flags); |
| 10049 globals_.Clear(); | 10011 globals_.Clear(); |
| 10050 } | 10012 } |
| 10051 } | 10013 } |
| 10052 | 10014 |
| 10053 | 10015 |
| 10054 void HOptimizedGraphBuilder::VisitVariableDeclaration( | 10016 void HOptimizedGraphBuilder::VisitVariableDeclaration( |
| 10055 VariableDeclaration* declaration) { | 10017 VariableDeclaration* declaration) { |
| 10056 VariableProxy* proxy = declaration->proxy(); | 10018 VariableProxy* proxy = declaration->proxy(); |
| 10057 VariableMode mode = declaration->mode(); | 10019 VariableMode mode = declaration->mode(); |
| 10058 Variable* variable = proxy->var(); | 10020 Variable* variable = proxy->var(); |
| 10059 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET; | 10021 bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY; |
| 10060 switch (variable->location()) { | 10022 switch (variable->location()) { |
| 10061 case Variable::UNALLOCATED: | 10023 case Variable::UNALLOCATED: |
| 10062 globals_.Add(variable->name(), zone()); | 10024 globals_.Add(variable->name(), zone()); |
| 10063 globals_.Add(variable->binding_needs_init() | 10025 globals_.Add(variable->binding_needs_init() |
| 10064 ? isolate()->factory()->the_hole_value() | 10026 ? isolate()->factory()->the_hole_value() |
| 10065 : isolate()->factory()->undefined_value(), zone()); | 10027 : isolate()->factory()->undefined_value(), zone()); |
| 10066 return; | 10028 return; |
| 10067 case Variable::PARAMETER: | 10029 case Variable::PARAMETER: |
| 10068 case Variable::LOCAL: | 10030 case Variable::LOCAL: |
| 10069 if (hole_init) { | 10031 if (hole_init) { |
| (...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10497 HValue* right = Pop(); | 10459 HValue* right = Pop(); |
| 10498 HValue* left = Pop(); | 10460 HValue* left = Pop(); |
| 10499 HInstruction* result = NewUncasted<HStringAdd>(left, right); | 10461 HInstruction* result = NewUncasted<HStringAdd>(left, right); |
| 10500 return ast_context()->ReturnInstruction(result, call->id()); | 10462 return ast_context()->ReturnInstruction(result, call->id()); |
| 10501 } | 10463 } |
| 10502 | 10464 |
| 10503 | 10465 |
| 10504 // Fast support for SubString. | 10466 // Fast support for SubString. |
| 10505 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { | 10467 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { |
| 10506 ASSERT_EQ(3, call->arguments()->length()); | 10468 ASSERT_EQ(3, call->arguments()->length()); |
| 10507 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 10469 CHECK_ALIVE(VisitExpressions(call->arguments())); |
| 10470 PushArgumentsFromEnvironment(call->arguments()->length()); |
| 10508 HCallStub* result = New<HCallStub>(CodeStub::SubString, 3); | 10471 HCallStub* result = New<HCallStub>(CodeStub::SubString, 3); |
| 10509 Drop(3); | |
| 10510 return ast_context()->ReturnInstruction(result, call->id()); | 10472 return ast_context()->ReturnInstruction(result, call->id()); |
| 10511 } | 10473 } |
| 10512 | 10474 |
| 10513 | 10475 |
| 10514 // Fast support for StringCompare. | 10476 // Fast support for StringCompare. |
| 10515 void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) { | 10477 void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) { |
| 10516 ASSERT_EQ(2, call->arguments()->length()); | 10478 ASSERT_EQ(2, call->arguments()->length()); |
| 10517 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 10479 CHECK_ALIVE(VisitExpressions(call->arguments())); |
| 10480 PushArgumentsFromEnvironment(call->arguments()->length()); |
| 10518 HCallStub* result = New<HCallStub>(CodeStub::StringCompare, 2); | 10481 HCallStub* result = New<HCallStub>(CodeStub::StringCompare, 2); |
| 10519 Drop(2); | |
| 10520 return ast_context()->ReturnInstruction(result, call->id()); | 10482 return ast_context()->ReturnInstruction(result, call->id()); |
| 10521 } | 10483 } |
| 10522 | 10484 |
| 10523 | 10485 |
| 10524 // Support for direct calls from JavaScript to native RegExp code. | 10486 // Support for direct calls from JavaScript to native RegExp code. |
| 10525 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) { | 10487 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) { |
| 10526 ASSERT_EQ(4, call->arguments()->length()); | 10488 ASSERT_EQ(4, call->arguments()->length()); |
| 10527 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 10489 CHECK_ALIVE(VisitExpressions(call->arguments())); |
| 10490 PushArgumentsFromEnvironment(call->arguments()->length()); |
| 10528 HCallStub* result = New<HCallStub>(CodeStub::RegExpExec, 4); | 10491 HCallStub* result = New<HCallStub>(CodeStub::RegExpExec, 4); |
| 10529 Drop(4); | |
| 10530 return ast_context()->ReturnInstruction(result, call->id()); | 10492 return ast_context()->ReturnInstruction(result, call->id()); |
| 10531 } | 10493 } |
| 10532 | 10494 |
| 10495 |
| 10496 void HOptimizedGraphBuilder::GenerateDoubleLo(CallRuntime* call) { |
| 10497 ASSERT_EQ(1, call->arguments()->length()); |
| 10498 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 10499 HValue* value = Pop(); |
| 10500 HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::LOW); |
| 10501 return ast_context()->ReturnInstruction(result, call->id()); |
| 10502 } |
| 10503 |
| 10504 |
| 10505 void HOptimizedGraphBuilder::GenerateDoubleHi(CallRuntime* call) { |
| 10506 ASSERT_EQ(1, call->arguments()->length()); |
| 10507 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 10508 HValue* value = Pop(); |
| 10509 HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::HIGH); |
| 10510 return ast_context()->ReturnInstruction(result, call->id()); |
| 10511 } |
| 10512 |
| 10513 |
| 10514 void HOptimizedGraphBuilder::GenerateConstructDouble(CallRuntime* call) { |
| 10515 ASSERT_EQ(2, call->arguments()->length()); |
| 10516 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 10517 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| 10518 HValue* lo = Pop(); |
| 10519 HValue* hi = Pop(); |
| 10520 HInstruction* result = NewUncasted<HConstructDouble>(hi, lo); |
| 10521 return ast_context()->ReturnInstruction(result, call->id()); |
| 10522 } |
| 10523 |
| 10533 | 10524 |
| 10534 // Construct a RegExp exec result with two in-object properties. | 10525 // Construct a RegExp exec result with two in-object properties. |
| 10535 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { | 10526 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { |
| 10536 ASSERT_EQ(3, call->arguments()->length()); | 10527 ASSERT_EQ(3, call->arguments()->length()); |
| 10537 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 10528 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 10538 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 10529 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| 10539 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); | 10530 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); |
| 10540 HValue* input = Pop(); | 10531 HValue* input = Pop(); |
| 10541 HValue* index = Pop(); | 10532 HValue* index = Pop(); |
| 10542 HValue* length = Pop(); | 10533 HValue* length = Pop(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 10560 return ast_context()->ReturnValue(result); | 10551 return ast_context()->ReturnValue(result); |
| 10561 } | 10552 } |
| 10562 | 10553 |
| 10563 | 10554 |
| 10564 // Fast call for custom callbacks. | 10555 // Fast call for custom callbacks. |
| 10565 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { | 10556 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { |
| 10566 // 1 ~ The function to call is not itself an argument to the call. | 10557 // 1 ~ The function to call is not itself an argument to the call. |
| 10567 int arg_count = call->arguments()->length() - 1; | 10558 int arg_count = call->arguments()->length() - 1; |
| 10568 ASSERT(arg_count >= 1); // There's always at least a receiver. | 10559 ASSERT(arg_count >= 1); // There's always at least a receiver. |
| 10569 | 10560 |
| 10570 for (int i = 0; i < arg_count; ++i) { | 10561 CHECK_ALIVE(VisitExpressions(call->arguments())); |
| 10571 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); | 10562 // The function is the last argument |
| 10572 } | |
| 10573 CHECK_ALIVE(VisitForValue(call->arguments()->last())); | |
| 10574 | |
| 10575 HValue* function = Pop(); | 10563 HValue* function = Pop(); |
| 10564 // Push the arguments to the stack |
| 10565 PushArgumentsFromEnvironment(arg_count); |
| 10576 | 10566 |
| 10577 IfBuilder if_is_jsfunction(this); | 10567 IfBuilder if_is_jsfunction(this); |
| 10578 if_is_jsfunction.If<HHasInstanceTypeAndBranch>(function, JS_FUNCTION_TYPE); | 10568 if_is_jsfunction.If<HHasInstanceTypeAndBranch>(function, JS_FUNCTION_TYPE); |
| 10579 | 10569 |
| 10580 if_is_jsfunction.Then(); | 10570 if_is_jsfunction.Then(); |
| 10581 { | 10571 { |
| 10582 HInstruction* invoke_result = | 10572 HInstruction* invoke_result = |
| 10583 Add<HInvokeFunction>(function, arg_count); | 10573 Add<HInvokeFunction>(function, arg_count); |
| 10584 Drop(arg_count); | |
| 10585 if (!ast_context()->IsEffect()) { | 10574 if (!ast_context()->IsEffect()) { |
| 10586 Push(invoke_result); | 10575 Push(invoke_result); |
| 10587 } | 10576 } |
| 10588 Add<HSimulate>(call->id(), FIXED_SIMULATE); | 10577 Add<HSimulate>(call->id(), FIXED_SIMULATE); |
| 10589 } | 10578 } |
| 10590 | 10579 |
| 10591 if_is_jsfunction.Else(); | 10580 if_is_jsfunction.Else(); |
| 10592 { | 10581 { |
| 10593 HInstruction* call_result = | 10582 HInstruction* call_result = |
| 10594 Add<HCallFunction>(function, arg_count); | 10583 Add<HCallFunction>(function, arg_count); |
| 10595 Drop(arg_count); | |
| 10596 if (!ast_context()->IsEffect()) { | 10584 if (!ast_context()->IsEffect()) { |
| 10597 Push(call_result); | 10585 Push(call_result); |
| 10598 } | 10586 } |
| 10599 Add<HSimulate>(call->id(), FIXED_SIMULATE); | 10587 Add<HSimulate>(call->id(), FIXED_SIMULATE); |
| 10600 } | 10588 } |
| 10601 if_is_jsfunction.End(); | 10589 if_is_jsfunction.End(); |
| 10602 | 10590 |
| 10603 if (ast_context()->IsEffect()) { | 10591 if (ast_context()->IsEffect()) { |
| 10604 // EffectContext::ReturnValue ignores the value, so we can just pass | 10592 // EffectContext::ReturnValue ignores the value, so we can just pass |
| 10605 // 'undefined' (as we do not have the call result anymore). | 10593 // 'undefined' (as we do not have the call result anymore). |
| (...skipping 692 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11298 if (ShouldProduceTraceOutput()) { | 11286 if (ShouldProduceTraceOutput()) { |
| 11299 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11287 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 11300 } | 11288 } |
| 11301 | 11289 |
| 11302 #ifdef DEBUG | 11290 #ifdef DEBUG |
| 11303 graph_->Verify(false); // No full verify. | 11291 graph_->Verify(false); // No full verify. |
| 11304 #endif | 11292 #endif |
| 11305 } | 11293 } |
| 11306 | 11294 |
| 11307 } } // namespace v8::internal | 11295 } } // namespace v8::internal |
| OLD | NEW |