| 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 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 218 it.Current()->RegisterPredecessor(this); | 218 it.Current()->RegisterPredecessor(this); |
| 219 } | 219 } |
| 220 } | 220 } |
| 221 | 221 |
| 222 | 222 |
| 223 void HBasicBlock::Goto(HBasicBlock* block, | 223 void HBasicBlock::Goto(HBasicBlock* block, |
| 224 int position, | 224 int position, |
| 225 FunctionState* state, | 225 FunctionState* state, |
| 226 bool add_simulate) { | 226 bool add_simulate) { |
| 227 bool drop_extra = state != NULL && | 227 bool drop_extra = state != NULL && |
| 228 state->inlining_kind() == DROP_EXTRA_ON_RETURN; | 228 state->inlining_kind() == NORMAL_RETURN; |
| 229 | 229 |
| 230 if (block->IsInlineReturnTarget()) { | 230 if (block->IsInlineReturnTarget()) { |
| 231 HEnvironment* env = last_environment(); | 231 HEnvironment* env = last_environment(); |
| 232 int argument_count = env->arguments_environment()->parameter_count(); | 232 int argument_count = env->arguments_environment()->parameter_count(); |
| 233 AddInstruction(new(zone()) | 233 AddInstruction(new(zone()) |
| 234 HLeaveInlined(state->entry(), argument_count), | 234 HLeaveInlined(state->entry(), argument_count), |
| 235 position); | 235 position); |
| 236 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); | 236 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); |
| 237 } | 237 } |
| 238 | 238 |
| 239 if (add_simulate) AddNewSimulate(BailoutId::None(), position); | 239 if (add_simulate) AddNewSimulate(BailoutId::None(), position); |
| 240 HGoto* instr = new(zone()) HGoto(block); | 240 HGoto* instr = new(zone()) HGoto(block); |
| 241 Finish(instr, position); | 241 Finish(instr, position); |
| 242 } | 242 } |
| 243 | 243 |
| 244 | 244 |
| 245 void HBasicBlock::AddLeaveInlined(HValue* return_value, | 245 void HBasicBlock::AddLeaveInlined(HValue* return_value, |
| 246 FunctionState* state, | 246 FunctionState* state, |
| 247 int position) { | 247 int position) { |
| 248 HBasicBlock* target = state->function_return(); | 248 HBasicBlock* target = state->function_return(); |
| 249 bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN; | 249 bool drop_extra = state->inlining_kind() == NORMAL_RETURN; |
| 250 | 250 |
| 251 ASSERT(target->IsInlineReturnTarget()); | 251 ASSERT(target->IsInlineReturnTarget()); |
| 252 ASSERT(return_value != NULL); | 252 ASSERT(return_value != NULL); |
| 253 HEnvironment* env = last_environment(); | 253 HEnvironment* env = last_environment(); |
| 254 int argument_count = env->arguments_environment()->parameter_count(); | 254 int argument_count = env->arguments_environment()->parameter_count(); |
| 255 AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count), | 255 AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count), |
| 256 position); | 256 position); |
| 257 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); | 257 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); |
| 258 last_environment()->Push(return_value); | 258 last_environment()->Push(return_value); |
| 259 AddNewSimulate(BailoutId::None(), position); | 259 AddNewSimulate(BailoutId::None(), position); |
| (...skipping 5405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5665 } | 5665 } |
| 5666 | 5666 |
| 5667 if (!info->lookup()->IsFound()) return graph()->GetConstantUndefined(); | 5667 if (!info->lookup()->IsFound()) return graph()->GetConstantUndefined(); |
| 5668 | 5668 |
| 5669 if (info->lookup()->IsField()) { | 5669 if (info->lookup()->IsField()) { |
| 5670 return BuildLoadNamedField(checked_holder, info->access()); | 5670 return BuildLoadNamedField(checked_holder, info->access()); |
| 5671 } | 5671 } |
| 5672 | 5672 |
| 5673 if (info->lookup()->IsPropertyCallbacks()) { | 5673 if (info->lookup()->IsPropertyCallbacks()) { |
| 5674 if (NeedsWrappingFor(info->type(), info->accessor())) { | 5674 if (NeedsWrappingFor(info->type(), info->accessor())) { |
| 5675 return New<HLoadNamedGeneric>(checked_object, info->name()); | 5675 HValue* function = Add<HConstant>(info->accessor()); |
| 5676 // HValue* function = Add<HConstant>(info->accessor()); | 5676 Add<HPushArgument>(checked_object); |
| 5677 // Add<HPushArgument>(checked_object); | 5677 return New<HCallFunction>(function, 1, WRAP_AND_CALL); |
| 5678 // return New<HCallFunction>(function, 1, WRAP_AND_CALL); | |
| 5679 } else { | 5678 } else { |
| 5680 Push(checked_object); | 5679 Push(checked_object); |
| 5681 if (FLAG_inline_accessors && | 5680 if (FLAG_inline_accessors && |
| 5682 can_inline_accessor && | 5681 can_inline_accessor && |
| 5683 TryInlineGetter(info->accessor(), ast_id, return_id)) { | 5682 TryInlineGetter(info->accessor(), ast_id, return_id)) { |
| 5684 return NULL; | 5683 return NULL; |
| 5685 } | 5684 } |
| 5686 Add<HPushArgument>(Pop()); | 5685 Add<HPushArgument>(Pop()); |
| 5687 return BuildCallConstantFunction(info->accessor(), 1); | 5686 return BuildCallConstantFunction(info->accessor(), 1); |
| 5688 } | 5687 } |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6020 Handle<JSObject> holder; | 6019 Handle<JSObject> holder; |
| 6021 if (LookupSetter(map, name, &setter, &holder)) { | 6020 if (LookupSetter(map, name, &setter, &holder)) { |
| 6022 AddCheckMap(object, map); | 6021 AddCheckMap(object, map); |
| 6023 AddCheckPrototypeMaps(holder, map); | 6022 AddCheckPrototypeMaps(holder, map); |
| 6024 bool needs_wrapping = NeedsWrappingFor(IC::MapToType(map), setter); | 6023 bool needs_wrapping = NeedsWrappingFor(IC::MapToType(map), setter); |
| 6025 bool try_inline = FLAG_inline_accessors && !needs_wrapping; | 6024 bool try_inline = FLAG_inline_accessors && !needs_wrapping; |
| 6026 if (try_inline && TryInlineSetter(setter, ast_id, return_id, value)) { | 6025 if (try_inline && TryInlineSetter(setter, ast_id, return_id, value)) { |
| 6027 return; | 6026 return; |
| 6028 } | 6027 } |
| 6029 Drop(2); | 6028 Drop(2); |
| 6029 Add<HPushArgument>(object); |
| 6030 Add<HPushArgument>(value); |
| 6030 if (needs_wrapping) { | 6031 if (needs_wrapping) { |
| 6031 instr = BuildStoreNamedGeneric(object, name, value); | 6032 HValue* function = Add<HConstant>(setter); |
| 6033 instr = New<HCallFunction>(function, 2, WRAP_AND_CALL); |
| 6032 } else { | 6034 } else { |
| 6033 Add<HPushArgument>(object); | |
| 6034 Add<HPushArgument>(value); | |
| 6035 instr = BuildCallConstantFunction(setter, 2); | 6035 instr = BuildCallConstantFunction(setter, 2); |
| 6036 } | 6036 } |
| 6037 } else { | 6037 } else { |
| 6038 Drop(2); | 6038 Drop(2); |
| 6039 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, | 6039 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, |
| 6040 name, | 6040 name, |
| 6041 value, | 6041 value, |
| 6042 map)); | 6042 map)); |
| 6043 } | 6043 } |
| 6044 } else if (types != NULL && types->length() > 1) { | 6044 } else if (types != NULL && types->length() > 1) { |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6422 } | 6422 } |
| 6423 } | 6423 } |
| 6424 return AddLoadNamedField(string, HObjectAccess::ForStringLength()); | 6424 return AddLoadNamedField(string, HObjectAccess::ForStringLength()); |
| 6425 } | 6425 } |
| 6426 | 6426 |
| 6427 | 6427 |
| 6428 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 6428 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( |
| 6429 HValue* object, | 6429 HValue* object, |
| 6430 Handle<String> name, | 6430 Handle<String> name, |
| 6431 Property* expr) { | 6431 Property* expr) { |
| 6432 if (expr->IsUninitialized()) { | 6432 if (!expr->IsForCall() && expr->IsUninitialized()) { |
| 6433 Add<HDeoptimize>("Insufficient type feedback for generic named load", | 6433 Add<HDeoptimize>("Insufficient type feedback for generic named load", |
| 6434 Deoptimizer::SOFT); | 6434 Deoptimizer::SOFT); |
| 6435 } | 6435 } |
| 6436 return New<HLoadNamedGeneric>(object, name); | 6436 return New<HLoadNamedGeneric>(object, name); |
| 6437 } | 6437 } |
| 6438 | 6438 |
| 6439 | 6439 |
| 6440 | 6440 |
| 6441 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 6441 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
| 6442 HValue* key) { | 6442 HValue* key) { |
| (...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6984 | 6984 |
| 6985 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, | 6985 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, |
| 6986 Handle<Map> receiver_map) { | 6986 Handle<Map> receiver_map) { |
| 6987 if (!holder.is_null()) { | 6987 if (!holder.is_null()) { |
| 6988 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); | 6988 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); |
| 6989 BuildCheckPrototypeMaps(prototype, holder); | 6989 BuildCheckPrototypeMaps(prototype, holder); |
| 6990 } | 6990 } |
| 6991 } | 6991 } |
| 6992 | 6992 |
| 6993 | 6993 |
| 6994 void HOptimizedGraphBuilder::AddCheckConstantFunction( | |
| 6995 Handle<JSObject> holder, | |
| 6996 HValue* receiver, | |
| 6997 Handle<Map> receiver_map) { | |
| 6998 // Constant functions have the nice property that the map will change if they | |
| 6999 // are overwritten. Therefore it is enough to check the map of the holder and | |
| 7000 // its prototypes. | |
| 7001 AddCheckMap(receiver, receiver_map); | |
| 7002 AddCheckPrototypeMaps(holder, receiver_map); | |
| 7003 } | |
| 7004 | |
| 7005 | |
| 7006 HInstruction* HOptimizedGraphBuilder::NewPlainFunctionCall( | 6994 HInstruction* HOptimizedGraphBuilder::NewPlainFunctionCall( |
| 7007 HValue* fun, int argument_count, bool pass_argument_count) { | 6995 HValue* fun, int argument_count, bool pass_argument_count) { |
| 7008 return New<HCallJSFunction>( | 6996 return New<HCallJSFunction>( |
| 7009 fun, argument_count, pass_argument_count); | 6997 fun, argument_count, pass_argument_count); |
| 7010 } | 6998 } |
| 7011 | 6999 |
| 7012 | 7000 |
| 7013 HInstruction* HOptimizedGraphBuilder::NewArgumentAdaptorCall( | 7001 HInstruction* HOptimizedGraphBuilder::NewArgumentAdaptorCall( |
| 7014 HValue* fun, HValue* context, | 7002 HValue* fun, HValue* context, |
| 7015 int argument_count, HValue* expected_param_count) { | 7003 int argument_count, HValue* expected_param_count) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 7036 // For constant functions, we try to avoid calling the | 7024 // For constant functions, we try to avoid calling the |
| 7037 // argument adaptor and instead call the function directly | 7025 // argument adaptor and instead call the function directly |
| 7038 int formal_parameter_count = jsfun->shared()->formal_parameter_count(); | 7026 int formal_parameter_count = jsfun->shared()->formal_parameter_count(); |
| 7039 bool dont_adapt_arguments = | 7027 bool dont_adapt_arguments = |
| 7040 (formal_parameter_count == | 7028 (formal_parameter_count == |
| 7041 SharedFunctionInfo::kDontAdaptArgumentsSentinel); | 7029 SharedFunctionInfo::kDontAdaptArgumentsSentinel); |
| 7042 int arity = argument_count - 1; | 7030 int arity = argument_count - 1; |
| 7043 bool can_invoke_directly = | 7031 bool can_invoke_directly = |
| 7044 dont_adapt_arguments || formal_parameter_count == arity; | 7032 dont_adapt_arguments || formal_parameter_count == arity; |
| 7045 if (can_invoke_directly) { | 7033 if (can_invoke_directly) { |
| 7034 if (jsfun.is_identical_to(current_info()->closure())) { |
| 7035 graph()->MarkRecursive(); |
| 7036 } |
| 7046 return NewPlainFunctionCall(target, argument_count, dont_adapt_arguments); | 7037 return NewPlainFunctionCall(target, argument_count, dont_adapt_arguments); |
| 7047 } else { | 7038 } else { |
| 7048 HValue* param_count_value = Add<HConstant>(formal_parameter_count); | 7039 HValue* param_count_value = Add<HConstant>(formal_parameter_count); |
| 7049 HValue* context = Add<HLoadNamedField>( | 7040 HValue* context = Add<HLoadNamedField>( |
| 7050 target, static_cast<HValue*>(NULL), | 7041 target, static_cast<HValue*>(NULL), |
| 7051 HObjectAccess::ForFunctionContextPointer()); | 7042 HObjectAccess::ForFunctionContextPointer()); |
| 7052 return NewArgumentAdaptorCall(target, context, | 7043 return NewArgumentAdaptorCall(target, context, |
| 7053 argument_count, param_count_value); | 7044 argument_count, param_count_value); |
| 7054 } | 7045 } |
| 7055 UNREACHABLE(); | 7046 UNREACHABLE(); |
| 7056 return NULL; | 7047 return NULL; |
| 7057 } | 7048 } |
| 7058 | 7049 |
| 7059 | 7050 |
| 7060 HInstruction* HOptimizedGraphBuilder::NewCallNamed( | |
| 7061 Handle<String> name, int argument_count) { | |
| 7062 CallInterfaceDescriptor* descriptor = | |
| 7063 isolate()->call_descriptor(Isolate::NamedCall); | |
| 7064 HValue* op_vals[] = { context(), Add<HConstant>(name) }; | |
| 7065 int arity = argument_count - 1; | |
| 7066 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arity); | |
| 7067 | |
| 7068 return New<HCallWithDescriptor>( | |
| 7069 Add<HConstant>(ic), argument_count, descriptor, | |
| 7070 Vector<HValue*>(op_vals, descriptor->environment_length())); | |
| 7071 } | |
| 7072 | |
| 7073 | |
| 7074 HInstruction* HOptimizedGraphBuilder::NewCallKeyed( | |
| 7075 HValue* key, int argument_count) { | |
| 7076 CallInterfaceDescriptor* descriptor = | |
| 7077 isolate()->call_descriptor(Isolate::KeyedCall); | |
| 7078 HValue* op_vals[] = { context(), key }; | |
| 7079 int arity = argument_count - 1; | |
| 7080 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); | |
| 7081 | |
| 7082 return New<HCallWithDescriptor>( | |
| 7083 Add<HConstant>(ic), argument_count, descriptor, | |
| 7084 Vector<HValue*>(op_vals, descriptor->environment_length())); | |
| 7085 } | |
| 7086 | |
| 7087 class FunctionSorter { | 7051 class FunctionSorter { |
| 7088 public: | 7052 public: |
| 7089 FunctionSorter() : index_(0), ticks_(0), ast_length_(0), src_length_(0) { } | 7053 FunctionSorter() : index_(0), ticks_(0), ast_length_(0), src_length_(0) { } |
| 7090 FunctionSorter(int index, int ticks, int ast_length, int src_length) | 7054 FunctionSorter(int index, int ticks, int ast_length, int src_length) |
| 7091 : index_(index), | 7055 : index_(index), |
| 7092 ticks_(ticks), | 7056 ticks_(ticks), |
| 7093 ast_length_(ast_length), | 7057 ast_length_(ast_length), |
| 7094 src_length_(src_length) { } | 7058 src_length_(src_length) { } |
| 7095 | 7059 |
| 7096 int index() const { return index_; } | 7060 int index() const { return index_; } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 7108 | 7072 |
| 7109 inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) { | 7073 inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) { |
| 7110 int diff = lhs.ticks() - rhs.ticks(); | 7074 int diff = lhs.ticks() - rhs.ticks(); |
| 7111 if (diff != 0) return diff > 0; | 7075 if (diff != 0) return diff > 0; |
| 7112 diff = lhs.ast_length() - rhs.ast_length(); | 7076 diff = lhs.ast_length() - rhs.ast_length(); |
| 7113 if (diff != 0) return diff < 0; | 7077 if (diff != 0) return diff < 0; |
| 7114 return lhs.src_length() < rhs.src_length(); | 7078 return lhs.src_length() < rhs.src_length(); |
| 7115 } | 7079 } |
| 7116 | 7080 |
| 7117 | 7081 |
| 7118 bool HOptimizedGraphBuilder::TryCallPolymorphicAsMonomorphic( | |
| 7119 Call* expr, | |
| 7120 HValue* receiver, | |
| 7121 SmallMapList* types, | |
| 7122 Handle<String> name) { | |
| 7123 if (types->length() > kMaxCallPolymorphism) return false; | |
| 7124 | |
| 7125 PropertyAccessInfo info(this, IC::MapToType(types->at(0)), name); | |
| 7126 if (!info.CanLoadAsMonomorphic(types)) return false; | |
| 7127 if (!expr->ComputeTarget(info.map(), name)) return false; | |
| 7128 | |
| 7129 BuildCheckHeapObject(receiver); | |
| 7130 Add<HCheckMaps>(receiver, types); | |
| 7131 AddCheckPrototypeMaps(expr->holder(), info.map()); | |
| 7132 if (FLAG_trace_inlining) { | |
| 7133 Handle<JSFunction> caller = current_info()->closure(); | |
| 7134 SmartArrayPointer<char> caller_name = | |
| 7135 caller->shared()->DebugName()->ToCString(); | |
| 7136 PrintF("Trying to inline the polymorphic call to %s from %s\n", | |
| 7137 name->ToCString().get(), caller_name.get()); | |
| 7138 } | |
| 7139 | |
| 7140 if (!TryInlineCall(expr)) { | |
| 7141 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | |
| 7142 HInstruction* call = BuildCallConstantFunction( | |
| 7143 expr->target(), argument_count); | |
| 7144 PushArgumentsFromEnvironment(argument_count); | |
| 7145 AddInstruction(call); | |
| 7146 if (!ast_context()->IsEffect()) Push(call); | |
| 7147 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | |
| 7148 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | |
| 7149 } | |
| 7150 | |
| 7151 return true; | |
| 7152 } | |
| 7153 | |
| 7154 | |
| 7155 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( | 7082 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( |
| 7156 Call* expr, | 7083 Call* expr, |
| 7157 HValue* receiver, | 7084 HValue* receiver, |
| 7158 SmallMapList* types, | 7085 SmallMapList* types, |
| 7159 Handle<String> name) { | 7086 Handle<String> name) { |
| 7160 if (TryCallPolymorphicAsMonomorphic(expr, receiver, types, name)) return; | |
| 7161 | |
| 7162 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 7087 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
| 7163 HBasicBlock* join = NULL; | |
| 7164 FunctionSorter order[kMaxCallPolymorphism]; | 7088 FunctionSorter order[kMaxCallPolymorphism]; |
| 7165 int ordered_functions = 0; | |
| 7166 | |
| 7167 Handle<Map> initial_string_map( | |
| 7168 isolate()->native_context()->string_function()->initial_map()); | |
| 7169 Handle<Map> string_marker_map( | |
| 7170 JSObject::cast(initial_string_map->prototype())->map()); | |
| 7171 Handle<Map> initial_number_map( | |
| 7172 isolate()->native_context()->number_function()->initial_map()); | |
| 7173 Handle<Map> number_marker_map( | |
| 7174 JSObject::cast(initial_number_map->prototype())->map()); | |
| 7175 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); | |
| 7176 | 7089 |
| 7177 bool handle_smi = false; | 7090 bool handle_smi = false; |
| 7091 bool handled_string = false; |
| 7092 int ordered_functions = 0; |
| 7178 | 7093 |
| 7179 for (int i = 0; | 7094 for (int i = 0; |
| 7180 i < types->length() && ordered_functions < kMaxCallPolymorphism; | 7095 i < types->length() && ordered_functions < kMaxCallPolymorphism; |
| 7181 ++i) { | 7096 ++i) { |
| 7182 Handle<Map> map = types->at(i); | 7097 PropertyAccessInfo info(this, IC::MapToType(types->at(i)), name); |
| 7183 if (expr->ComputeTarget(map, name)) { | 7098 if (info.CanLoadMonomorphic() && |
| 7184 if (map.is_identical_to(number_marker_map)) handle_smi = true; | 7099 info.lookup()->IsConstant() && |
| 7100 info.constant()->IsJSFunction()) { |
| 7101 if (info.type()->Is(HeapType::String())) { |
| 7102 if (handled_string) continue; |
| 7103 handled_string = true; |
| 7104 } |
| 7105 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant()); |
| 7106 if (info.type()->Is(HeapType::Number())) { |
| 7107 handle_smi = true; |
| 7108 } |
| 7109 expr->set_target(target); |
| 7185 order[ordered_functions++] = | 7110 order[ordered_functions++] = |
| 7186 FunctionSorter(i, | 7111 FunctionSorter(i, |
| 7187 expr->target()->shared()->profiler_ticks(), | 7112 expr->target()->shared()->profiler_ticks(), |
| 7188 InliningAstSize(expr->target()), | 7113 InliningAstSize(expr->target()), |
| 7189 expr->target()->shared()->SourceSize()); | 7114 expr->target()->shared()->SourceSize()); |
| 7190 } | 7115 } |
| 7191 } | 7116 } |
| 7192 | 7117 |
| 7193 std::sort(order, order + ordered_functions); | 7118 std::sort(order, order + ordered_functions); |
| 7194 | 7119 |
| 7195 HBasicBlock* number_block = NULL; | 7120 HBasicBlock* number_block = NULL; |
| 7121 HBasicBlock* join = NULL; |
| 7122 handled_string = false; |
| 7123 int count = 0; |
| 7196 | 7124 |
| 7197 for (int fn = 0; fn < ordered_functions; ++fn) { | 7125 for (int fn = 0; fn < ordered_functions; ++fn) { |
| 7198 int i = order[fn].index(); | 7126 int i = order[fn].index(); |
| 7199 Handle<Map> map = types->at(i); | 7127 PropertyAccessInfo info(this, IC::MapToType(types->at(i)), name); |
| 7200 if (fn == 0) { | 7128 if (info.type()->Is(HeapType::String())) { |
| 7129 if (handled_string) continue; |
| 7130 handled_string = true; |
| 7131 } |
| 7132 // Reloads the target. |
| 7133 info.CanLoadMonomorphic(); |
| 7134 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant()); |
| 7135 |
| 7136 expr->set_target(target); |
| 7137 if (count == 0) { |
| 7201 // Only needed once. | 7138 // Only needed once. |
| 7202 join = graph()->CreateBasicBlock(); | 7139 join = graph()->CreateBasicBlock(); |
| 7203 if (handle_smi) { | 7140 if (handle_smi) { |
| 7204 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); | 7141 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); |
| 7205 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); | 7142 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); |
| 7206 number_block = graph()->CreateBasicBlock(); | 7143 number_block = graph()->CreateBasicBlock(); |
| 7207 FinishCurrentBlock(New<HIsSmiAndBranch>( | 7144 FinishCurrentBlock(New<HIsSmiAndBranch>( |
| 7208 receiver, empty_smi_block, not_smi_block)); | 7145 receiver, empty_smi_block, not_smi_block)); |
| 7209 Goto(empty_smi_block, number_block); | 7146 Goto(empty_smi_block, number_block); |
| 7210 set_current_block(not_smi_block); | 7147 set_current_block(not_smi_block); |
| 7211 } else { | 7148 } else { |
| 7212 BuildCheckHeapObject(receiver); | 7149 BuildCheckHeapObject(receiver); |
| 7213 } | 7150 } |
| 7214 } | 7151 } |
| 7152 ++count; |
| 7215 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 7153 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| 7216 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 7154 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 7217 HUnaryControlInstruction* compare; | 7155 HUnaryControlInstruction* compare; |
| 7218 | 7156 |
| 7219 if (handle_smi && map.is_identical_to(number_marker_map)) { | 7157 Handle<Map> map = info.map(); |
| 7158 if (info.type()->Is(HeapType::Number())) { |
| 7159 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); |
| 7220 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false); | 7160 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false); |
| 7221 map = initial_number_map; | 7161 } else if (info.type()->Is(HeapType::String())) { |
| 7222 expr->set_number_check( | |
| 7223 Handle<JSObject>(JSObject::cast(map->prototype()))); | |
| 7224 } else if (map.is_identical_to(string_marker_map)) { | |
| 7225 compare = New<HIsStringAndBranch>(receiver, if_true, if_false); | 7162 compare = New<HIsStringAndBranch>(receiver, if_true, if_false); |
| 7226 map = initial_string_map; | |
| 7227 expr->set_string_check( | |
| 7228 Handle<JSObject>(JSObject::cast(map->prototype()))); | |
| 7229 } else { | 7163 } else { |
| 7230 compare = New<HCompareMap>(receiver, map, if_true, if_false); | 7164 compare = New<HCompareMap>(receiver, map, if_true, if_false); |
| 7231 expr->set_map_check(); | |
| 7232 } | 7165 } |
| 7233 | |
| 7234 FinishCurrentBlock(compare); | 7166 FinishCurrentBlock(compare); |
| 7235 | 7167 |
| 7236 if (expr->check_type() == NUMBER_CHECK) { | 7168 if (info.type()->Is(HeapType::Number())) { |
| 7237 Goto(if_true, number_block); | 7169 Goto(if_true, number_block); |
| 7238 if_true = number_block; | 7170 if_true = number_block; |
| 7239 number_block->SetJoinId(expr->id()); | 7171 number_block->SetJoinId(expr->id()); |
| 7240 } | 7172 } |
| 7173 |
| 7241 set_current_block(if_true); | 7174 set_current_block(if_true); |
| 7242 | 7175 |
| 7243 expr->ComputeTarget(map, name); | 7176 AddCheckPrototypeMaps(info.holder(), map); |
| 7244 AddCheckPrototypeMaps(expr->holder(), map); | 7177 |
| 7245 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { | 7178 HValue* function = Add<HConstant>(expr->target()); |
| 7179 environment()->SetExpressionStackAt(0, function); |
| 7180 Push(receiver); |
| 7181 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 7182 bool needs_wrapping = NeedsWrappingFor(info.type(), target); |
| 7183 bool try_inline = FLAG_polymorphic_inlining && !needs_wrapping; |
| 7184 if (FLAG_trace_inlining && try_inline) { |
| 7246 Handle<JSFunction> caller = current_info()->closure(); | 7185 Handle<JSFunction> caller = current_info()->closure(); |
| 7247 SmartArrayPointer<char> caller_name = | 7186 SmartArrayPointer<char> caller_name = |
| 7248 caller->shared()->DebugName()->ToCString(); | 7187 caller->shared()->DebugName()->ToCString(); |
| 7249 PrintF("Trying to inline the polymorphic call to %s from %s\n", | 7188 PrintF("Trying to inline the polymorphic call to %s from %s\n", |
| 7250 name->ToCString().get(), | 7189 name->ToCString().get(), |
| 7251 caller_name.get()); | 7190 caller_name.get()); |
| 7252 } | 7191 } |
| 7253 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { | 7192 if (try_inline && TryInlineCall(expr)) { |
| 7254 // Trying to inline will signal that we should bailout from the | 7193 // Trying to inline will signal that we should bailout from the |
| 7255 // entire compilation by setting stack overflow on the visitor. | 7194 // entire compilation by setting stack overflow on the visitor. |
| 7256 if (HasStackOverflow()) return; | 7195 if (HasStackOverflow()) return; |
| 7257 } else { | 7196 } else { |
| 7258 HInstruction* call = BuildCallConstantFunction( | 7197 // Since HWrapReceiver currently cannot actually wrap numbers and strings, |
| 7259 expr->target(), argument_count); | 7198 // use the regular CallFunctionStub for method calls to wrap the receiver. |
| 7199 // TODO(verwaest): Support creation of value wrappers directly in |
| 7200 // HWrapReceiver. |
| 7201 HInstruction* call = needs_wrapping |
| 7202 ? NewUncasted<HCallFunction>( |
| 7203 function, argument_count, WRAP_AND_CALL) |
| 7204 : BuildCallConstantFunction(target, argument_count); |
| 7260 PushArgumentsFromEnvironment(argument_count); | 7205 PushArgumentsFromEnvironment(argument_count); |
| 7261 AddInstruction(call); | 7206 AddInstruction(call); |
| 7207 Drop(1); // Drop the function. |
| 7262 if (!ast_context()->IsEffect()) Push(call); | 7208 if (!ast_context()->IsEffect()) Push(call); |
| 7263 } | 7209 } |
| 7264 | 7210 |
| 7265 if (current_block() != NULL) Goto(join); | 7211 if (current_block() != NULL) Goto(join); |
| 7266 set_current_block(if_false); | 7212 set_current_block(if_false); |
| 7267 } | 7213 } |
| 7268 | 7214 |
| 7269 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 7215 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
| 7270 // know about and do not want to handle ones we've never seen. Otherwise | 7216 // know about and do not want to handle ones we've never seen. Otherwise |
| 7271 // use a generic IC. | 7217 // use a generic IC. |
| 7272 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { | 7218 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { |
| 7273 // Because the deopt may be the only path in the polymorphic call, make sure | 7219 // Because the deopt may be the only path in the polymorphic call, make sure |
| 7274 // that the environment stack matches the depth on deopt that it otherwise | 7220 // that the environment stack matches the depth on deopt that it otherwise |
| 7275 // would have had after a successful call. | 7221 // would have had after a successful call. |
| 7276 Drop(argument_count); | 7222 Drop(1); // Drop receiver. |
| 7277 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); | 7223 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); |
| 7278 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); | 7224 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); |
| 7279 } else { | 7225 } else { |
| 7280 HInstruction* call = NewCallNamed(name, argument_count); | 7226 Property* prop = expr->expression()->AsProperty(); |
| 7227 HInstruction* function = BuildLoadNamedGeneric(receiver, name, prop); |
| 7228 AddInstruction(function); |
| 7229 Push(function); |
| 7230 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
| 7231 |
| 7232 environment()->SetExpressionStackAt(1, function); |
| 7233 environment()->SetExpressionStackAt(0, receiver); |
| 7234 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 7235 |
| 7236 CallFunctionFlags flags = receiver->type().IsJSObject() |
| 7237 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD; |
| 7238 HInstruction* call = New<HCallFunction>( |
| 7239 function, argument_count, flags); |
| 7240 |
| 7281 PushArgumentsFromEnvironment(argument_count); | 7241 PushArgumentsFromEnvironment(argument_count); |
| 7282 | 7242 |
| 7243 Drop(1); // Function. |
| 7244 |
| 7283 if (join != NULL) { | 7245 if (join != NULL) { |
| 7284 AddInstruction(call); | 7246 AddInstruction(call); |
| 7285 if (!ast_context()->IsEffect()) Push(call); | 7247 if (!ast_context()->IsEffect()) Push(call); |
| 7286 Goto(join); | 7248 Goto(join); |
| 7287 } else { | 7249 } else { |
| 7288 return ast_context()->ReturnInstruction(call, expr->id()); | 7250 return ast_context()->ReturnInstruction(call, expr->id()); |
| 7289 } | 7251 } |
| 7290 } | 7252 } |
| 7291 | 7253 |
| 7292 // We assume that control flow is always live after an expression. So | 7254 // We assume that control flow is always live after an expression. So |
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7636 function_return()->SetJoinId(ast_id); | 7598 function_return()->SetJoinId(ast_id); |
| 7637 set_current_block(function_return()); | 7599 set_current_block(function_return()); |
| 7638 } else { | 7600 } else { |
| 7639 set_current_block(NULL); | 7601 set_current_block(NULL); |
| 7640 } | 7602 } |
| 7641 delete target_state; | 7603 delete target_state; |
| 7642 return true; | 7604 return true; |
| 7643 } | 7605 } |
| 7644 | 7606 |
| 7645 | 7607 |
| 7646 bool HOptimizedGraphBuilder::TryInlineCall(Call* expr, bool drop_extra) { | 7608 bool HOptimizedGraphBuilder::TryInlineCall(Call* expr) { |
| 7647 return TryInline(expr->target(), | 7609 return TryInline(expr->target(), |
| 7648 expr->arguments()->length(), | 7610 expr->arguments()->length(), |
| 7649 NULL, | 7611 NULL, |
| 7650 expr->id(), | 7612 expr->id(), |
| 7651 expr->ReturnId(), | 7613 expr->ReturnId(), |
| 7652 drop_extra ? DROP_EXTRA_ON_RETURN : NORMAL_RETURN); | 7614 NORMAL_RETURN); |
| 7653 } | 7615 } |
| 7654 | 7616 |
| 7655 | 7617 |
| 7656 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr, | 7618 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr, |
| 7657 HValue* implicit_return_value) { | 7619 HValue* implicit_return_value) { |
| 7658 return TryInline(expr->target(), | 7620 return TryInline(expr->target(), |
| 7659 expr->arguments()->length(), | 7621 expr->arguments()->length(), |
| 7660 implicit_return_value, | 7622 implicit_return_value, |
| 7661 expr->id(), | 7623 expr->id(), |
| 7662 expr->ReturnId(), | 7624 expr->ReturnId(), |
| (...skipping 30 matching lines...) Expand all Loading... |
| 7693 int arguments_count) { | 7655 int arguments_count) { |
| 7694 return TryInline(function, | 7656 return TryInline(function, |
| 7695 arguments_count, | 7657 arguments_count, |
| 7696 NULL, | 7658 NULL, |
| 7697 expr->id(), | 7659 expr->id(), |
| 7698 expr->ReturnId(), | 7660 expr->ReturnId(), |
| 7699 NORMAL_RETURN); | 7661 NORMAL_RETURN); |
| 7700 } | 7662 } |
| 7701 | 7663 |
| 7702 | 7664 |
| 7703 bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, | 7665 bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr) { |
| 7704 bool drop_extra) { | |
| 7705 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; | 7666 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; |
| 7706 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); | 7667 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); |
| 7707 switch (id) { | 7668 switch (id) { |
| 7708 case kMathExp: | 7669 case kMathExp: |
| 7709 if (!FLAG_fast_math) break; | 7670 if (!FLAG_fast_math) break; |
| 7710 // Fall through if FLAG_fast_math. | 7671 // Fall through if FLAG_fast_math. |
| 7711 case kMathRound: | 7672 case kMathRound: |
| 7712 case kMathFloor: | 7673 case kMathFloor: |
| 7713 case kMathAbs: | 7674 case kMathAbs: |
| 7714 case kMathSqrt: | 7675 case kMathSqrt: |
| 7715 case kMathLog: | 7676 case kMathLog: |
| 7716 if (expr->arguments()->length() == 1) { | 7677 if (expr->arguments()->length() == 1) { |
| 7717 HValue* argument = Pop(); | 7678 HValue* argument = Pop(); |
| 7718 Drop(1); // Receiver. | 7679 Drop(2); // Receiver and function. |
| 7719 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id); | 7680 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id); |
| 7720 if (drop_extra) Drop(1); // Optionally drop the function. | |
| 7721 ast_context()->ReturnInstruction(op, expr->id()); | 7681 ast_context()->ReturnInstruction(op, expr->id()); |
| 7722 return true; | 7682 return true; |
| 7723 } | 7683 } |
| 7724 break; | 7684 break; |
| 7725 case kMathImul: | 7685 case kMathImul: |
| 7726 if (expr->arguments()->length() == 2) { | 7686 if (expr->arguments()->length() == 2) { |
| 7727 HValue* right = Pop(); | 7687 HValue* right = Pop(); |
| 7728 HValue* left = Pop(); | 7688 HValue* left = Pop(); |
| 7729 Drop(1); // Receiver. | 7689 Drop(2); // Receiver and function. |
| 7730 HInstruction* op = HMul::NewImul(zone(), context(), left, right); | 7690 HInstruction* op = HMul::NewImul(zone(), context(), left, right); |
| 7731 if (drop_extra) Drop(1); // Optionally drop the function. | |
| 7732 ast_context()->ReturnInstruction(op, expr->id()); | 7691 ast_context()->ReturnInstruction(op, expr->id()); |
| 7733 return true; | 7692 return true; |
| 7734 } | 7693 } |
| 7735 break; | 7694 break; |
| 7736 default: | 7695 default: |
| 7737 // Not supported for inlining yet. | 7696 // Not supported for inlining yet. |
| 7738 break; | 7697 break; |
| 7739 } | 7698 } |
| 7740 return false; | 7699 return false; |
| 7741 } | 7700 } |
| 7742 | 7701 |
| 7743 | 7702 |
| 7744 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( | 7703 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( |
| 7745 Call* expr, | 7704 Call* expr, |
| 7746 HValue* receiver, | 7705 HValue* receiver, |
| 7747 Handle<Map> receiver_map, | 7706 Handle<Map> receiver_map) { |
| 7748 CheckType check_type) { | |
| 7749 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null()); | |
| 7750 // Try to inline calls like Math.* as operations in the calling function. | 7707 // Try to inline calls like Math.* as operations in the calling function. |
| 7751 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; | 7708 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; |
| 7752 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); | 7709 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); |
| 7753 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 7710 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
| 7754 switch (id) { | 7711 switch (id) { |
| 7755 case kStringCharCodeAt: | 7712 case kStringCharCodeAt: |
| 7756 case kStringCharAt: | 7713 case kStringCharAt: |
| 7757 if (argument_count == 2 && check_type == STRING_CHECK) { | 7714 if (argument_count == 2) { |
| 7758 HValue* index = Pop(); | 7715 HValue* index = Pop(); |
| 7759 HValue* string = Pop(); | 7716 HValue* string = Pop(); |
| 7760 ASSERT(!expr->holder().is_null()); | 7717 Drop(1); // Function. |
| 7761 BuildCheckPrototypeMaps(Call::GetPrototypeForPrimitiveCheck( | |
| 7762 STRING_CHECK, expr->holder()->GetIsolate()), | |
| 7763 expr->holder()); | |
| 7764 HInstruction* char_code = | 7718 HInstruction* char_code = |
| 7765 BuildStringCharCodeAt(string, index); | 7719 BuildStringCharCodeAt(string, index); |
| 7766 if (id == kStringCharCodeAt) { | 7720 if (id == kStringCharCodeAt) { |
| 7767 ast_context()->ReturnInstruction(char_code, expr->id()); | 7721 ast_context()->ReturnInstruction(char_code, expr->id()); |
| 7768 return true; | 7722 return true; |
| 7769 } | 7723 } |
| 7770 AddInstruction(char_code); | 7724 AddInstruction(char_code); |
| 7771 HInstruction* result = NewUncasted<HStringCharFromCode>(char_code); | 7725 HInstruction* result = NewUncasted<HStringCharFromCode>(char_code); |
| 7772 ast_context()->ReturnInstruction(result, expr->id()); | 7726 ast_context()->ReturnInstruction(result, expr->id()); |
| 7773 return true; | 7727 return true; |
| 7774 } | 7728 } |
| 7775 break; | 7729 break; |
| 7776 case kStringFromCharCode: | 7730 case kStringFromCharCode: |
| 7777 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { | 7731 if (argument_count == 2) { |
| 7778 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | |
| 7779 HValue* argument = Pop(); | 7732 HValue* argument = Pop(); |
| 7780 Drop(1); // Receiver. | 7733 Drop(2); // Receiver and function. |
| 7781 HInstruction* result = NewUncasted<HStringCharFromCode>(argument); | 7734 HInstruction* result = NewUncasted<HStringCharFromCode>(argument); |
| 7782 ast_context()->ReturnInstruction(result, expr->id()); | 7735 ast_context()->ReturnInstruction(result, expr->id()); |
| 7783 return true; | 7736 return true; |
| 7784 } | 7737 } |
| 7785 break; | 7738 break; |
| 7786 case kMathExp: | 7739 case kMathExp: |
| 7787 if (!FLAG_fast_math) break; | 7740 if (!FLAG_fast_math) break; |
| 7788 // Fall through if FLAG_fast_math. | 7741 // Fall through if FLAG_fast_math. |
| 7789 case kMathRound: | 7742 case kMathRound: |
| 7790 case kMathFloor: | 7743 case kMathFloor: |
| 7791 case kMathAbs: | 7744 case kMathAbs: |
| 7792 case kMathSqrt: | 7745 case kMathSqrt: |
| 7793 case kMathLog: | 7746 case kMathLog: |
| 7794 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { | 7747 if (argument_count == 2) { |
| 7795 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | |
| 7796 HValue* argument = Pop(); | 7748 HValue* argument = Pop(); |
| 7797 Drop(1); // Receiver. | 7749 Drop(2); // Receiver and function. |
| 7798 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id); | 7750 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id); |
| 7799 ast_context()->ReturnInstruction(op, expr->id()); | 7751 ast_context()->ReturnInstruction(op, expr->id()); |
| 7800 return true; | 7752 return true; |
| 7801 } | 7753 } |
| 7802 break; | 7754 break; |
| 7803 case kMathPow: | 7755 case kMathPow: |
| 7804 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { | 7756 if (argument_count == 3) { |
| 7805 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | |
| 7806 HValue* right = Pop(); | 7757 HValue* right = Pop(); |
| 7807 HValue* left = Pop(); | 7758 HValue* left = Pop(); |
| 7808 Pop(); // Pop receiver. | 7759 Drop(2); // Receiver and function. |
| 7809 HInstruction* result = NULL; | 7760 HInstruction* result = NULL; |
| 7810 // Use sqrt() if exponent is 0.5 or -0.5. | 7761 // Use sqrt() if exponent is 0.5 or -0.5. |
| 7811 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { | 7762 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { |
| 7812 double exponent = HConstant::cast(right)->DoubleValue(); | 7763 double exponent = HConstant::cast(right)->DoubleValue(); |
| 7813 if (exponent == 0.5) { | 7764 if (exponent == 0.5) { |
| 7814 result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf); | 7765 result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf); |
| 7815 } else if (exponent == -0.5) { | 7766 } else if (exponent == -0.5) { |
| 7816 HValue* one = graph()->GetConstant1(); | 7767 HValue* one = graph()->GetConstant1(); |
| 7817 HInstruction* sqrt = AddUncasted<HUnaryMathOperation>( | 7768 HInstruction* sqrt = AddUncasted<HUnaryMathOperation>( |
| 7818 left, kMathPowHalf); | 7769 left, kMathPowHalf); |
| 7819 // MathPowHalf doesn't have side effects so there's no need for | 7770 // MathPowHalf doesn't have side effects so there's no need for |
| 7820 // an environment simulation here. | 7771 // an environment simulation here. |
| 7821 ASSERT(!sqrt->HasObservableSideEffects()); | 7772 ASSERT(!sqrt->HasObservableSideEffects()); |
| 7822 result = NewUncasted<HDiv>(one, sqrt); | 7773 result = NewUncasted<HDiv>(one, sqrt); |
| 7823 } else if (exponent == 2.0) { | 7774 } else if (exponent == 2.0) { |
| 7824 result = NewUncasted<HMul>(left, left); | 7775 result = NewUncasted<HMul>(left, left); |
| 7825 } | 7776 } |
| 7826 } | 7777 } |
| 7827 | 7778 |
| 7828 if (result == NULL) { | 7779 if (result == NULL) { |
| 7829 result = NewUncasted<HPower>(left, right); | 7780 result = NewUncasted<HPower>(left, right); |
| 7830 } | 7781 } |
| 7831 ast_context()->ReturnInstruction(result, expr->id()); | 7782 ast_context()->ReturnInstruction(result, expr->id()); |
| 7832 return true; | 7783 return true; |
| 7833 } | 7784 } |
| 7834 break; | 7785 break; |
| 7835 case kMathMax: | 7786 case kMathMax: |
| 7836 case kMathMin: | 7787 case kMathMin: |
| 7837 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { | 7788 if (argument_count == 3) { |
| 7838 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | |
| 7839 HValue* right = Pop(); | 7789 HValue* right = Pop(); |
| 7840 HValue* left = Pop(); | 7790 HValue* left = Pop(); |
| 7841 Drop(1); // Receiver. | 7791 Drop(2); // Receiver and function. |
| 7842 HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin | 7792 HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin |
| 7843 : HMathMinMax::kMathMax; | 7793 : HMathMinMax::kMathMax; |
| 7844 HInstruction* result = NewUncasted<HMathMinMax>(left, right, op); | 7794 HInstruction* result = NewUncasted<HMathMinMax>(left, right, op); |
| 7845 ast_context()->ReturnInstruction(result, expr->id()); | 7795 ast_context()->ReturnInstruction(result, expr->id()); |
| 7846 return true; | 7796 return true; |
| 7847 } | 7797 } |
| 7848 break; | 7798 break; |
| 7849 case kMathImul: | 7799 case kMathImul: |
| 7850 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { | 7800 if (argument_count == 3) { |
| 7851 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | |
| 7852 HValue* right = Pop(); | 7801 HValue* right = Pop(); |
| 7853 HValue* left = Pop(); | 7802 HValue* left = Pop(); |
| 7854 Drop(1); // Receiver. | 7803 Drop(2); // Receiver and function. |
| 7855 HInstruction* result = HMul::NewImul(zone(), context(), left, right); | 7804 HInstruction* result = HMul::NewImul(zone(), context(), left, right); |
| 7856 ast_context()->ReturnInstruction(result, expr->id()); | 7805 ast_context()->ReturnInstruction(result, expr->id()); |
| 7857 return true; | 7806 return true; |
| 7858 } | 7807 } |
| 7859 break; | 7808 break; |
| 7860 case kArrayPop: { | 7809 case kArrayPop: { |
| 7861 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { | 7810 if (receiver_map.is_null()) return false; |
| 7862 return false; | |
| 7863 } | |
| 7864 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false; | 7811 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false; |
| 7865 ElementsKind elements_kind = receiver_map->elements_kind(); | 7812 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 7866 if (!IsFastElementsKind(elements_kind)) return false; | 7813 if (!IsFastElementsKind(elements_kind)) return false; |
| 7867 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | |
| 7868 | 7814 |
| 7869 Drop(expr->arguments()->length()); | 7815 Drop(expr->arguments()->length()); |
| 7870 HValue* result; | 7816 HValue* result; |
| 7871 HValue* reduced_length; | 7817 HValue* reduced_length; |
| 7872 HValue* receiver = Pop(); | 7818 HValue* receiver = Pop(); |
| 7873 | 7819 |
| 7874 HValue* checked_object = AddCheckMap(receiver, receiver_map); | 7820 HValue* checked_object = AddCheckMap(receiver, receiver_map); |
| 7875 HValue* length = Add<HLoadNamedField>( | 7821 HValue* length = Add<HLoadNamedField>( |
| 7876 checked_object, static_cast<HValue*>(NULL), | 7822 checked_object, static_cast<HValue*>(NULL), |
| 7877 HObjectAccess::ForArrayLength(elements_kind)); | 7823 HObjectAccess::ForArrayLength(elements_kind)); |
| 7878 | 7824 |
| 7825 Drop(1); // Function. |
| 7826 |
| 7879 { NoObservableSideEffectsScope scope(this); | 7827 { NoObservableSideEffectsScope scope(this); |
| 7880 IfBuilder length_checker(this); | 7828 IfBuilder length_checker(this); |
| 7881 | 7829 |
| 7882 HValue* bounds_check = length_checker.If<HCompareNumericAndBranch>( | 7830 HValue* bounds_check = length_checker.If<HCompareNumericAndBranch>( |
| 7883 length, graph()->GetConstant0(), Token::EQ); | 7831 length, graph()->GetConstant0(), Token::EQ); |
| 7884 length_checker.Then(); | 7832 length_checker.Then(); |
| 7885 | 7833 |
| 7886 if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined()); | 7834 if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined()); |
| 7887 | 7835 |
| 7888 length_checker.Else(); | 7836 length_checker.Else(); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 7914 length_checker.End(); | 7862 length_checker.End(); |
| 7915 } | 7863 } |
| 7916 result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top(); | 7864 result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top(); |
| 7917 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | 7865 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| 7918 if (!ast_context()->IsEffect()) Drop(1); | 7866 if (!ast_context()->IsEffect()) Drop(1); |
| 7919 | 7867 |
| 7920 ast_context()->ReturnValue(result); | 7868 ast_context()->ReturnValue(result); |
| 7921 return true; | 7869 return true; |
| 7922 } | 7870 } |
| 7923 case kArrayPush: { | 7871 case kArrayPush: { |
| 7924 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { | 7872 if (receiver_map.is_null()) return false; |
| 7925 return false; | |
| 7926 } | |
| 7927 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false; | 7873 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false; |
| 7928 ElementsKind elements_kind = receiver_map->elements_kind(); | 7874 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 7929 if (!IsFastElementsKind(elements_kind)) return false; | 7875 if (!IsFastElementsKind(elements_kind)) return false; |
| 7930 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | |
| 7931 | 7876 |
| 7932 HValue* op_vals[] = { | 7877 HValue* op_vals[] = { |
| 7933 context(), | 7878 context(), |
| 7934 // Receiver. | 7879 // Receiver. |
| 7935 environment()->ExpressionStackAt(expr->arguments()->length()) | 7880 environment()->ExpressionStackAt(expr->arguments()->length()) |
| 7936 }; | 7881 }; |
| 7937 | 7882 |
| 7938 const int argc = expr->arguments()->length(); | 7883 const int argc = expr->arguments()->length(); |
| 7939 // Includes receiver. | 7884 // Includes receiver. |
| 7940 PushArgumentsFromEnvironment(argc + 1); | 7885 PushArgumentsFromEnvironment(argc + 1); |
| 7941 | 7886 |
| 7942 CallInterfaceDescriptor* descriptor = | 7887 CallInterfaceDescriptor* descriptor = |
| 7943 isolate()->call_descriptor(Isolate::CallHandler); | 7888 isolate()->call_descriptor(Isolate::CallHandler); |
| 7944 | 7889 |
| 7945 ArrayPushStub stub(receiver_map->elements_kind(), argc); | 7890 ArrayPushStub stub(receiver_map->elements_kind(), argc); |
| 7946 Handle<Code> code = stub.GetCode(isolate()); | 7891 Handle<Code> code = stub.GetCode(isolate()); |
| 7947 HConstant* code_value = Add<HConstant>(code); | 7892 HConstant* code_value = Add<HConstant>(code); |
| 7948 | 7893 |
| 7949 ASSERT((sizeof(op_vals) / kPointerSize) == | 7894 ASSERT((sizeof(op_vals) / kPointerSize) == |
| 7950 descriptor->environment_length()); | 7895 descriptor->environment_length()); |
| 7951 | 7896 |
| 7952 HInstruction* call = New<HCallWithDescriptor>( | 7897 HInstruction* call = New<HCallWithDescriptor>( |
| 7953 code_value, argc + 1, descriptor, | 7898 code_value, argc + 1, descriptor, |
| 7954 Vector<HValue*>(op_vals, descriptor->environment_length())); | 7899 Vector<HValue*>(op_vals, descriptor->environment_length())); |
| 7900 Drop(1); // Drop function. |
| 7955 ast_context()->ReturnInstruction(call, expr->id()); | 7901 ast_context()->ReturnInstruction(call, expr->id()); |
| 7956 return true; | 7902 return true; |
| 7957 } | 7903 } |
| 7958 default: | 7904 default: |
| 7959 // Not yet supported for inlining. | 7905 // Not yet supported for inlining. |
| 7960 break; | 7906 break; |
| 7961 } | 7907 } |
| 7962 return false; | 7908 return false; |
| 7963 } | 7909 } |
| 7964 | 7910 |
| 7965 | 7911 |
| 7966 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr, | 7912 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr, |
| 7967 HValue* receiver, | 7913 HValue* receiver) { |
| 7968 bool drop_extra) { | |
| 7969 return TryInlineApiCall( | 7914 return TryInlineApiCall( |
| 7970 expr, receiver, Handle<Map>::null(), drop_extra, true); | 7915 expr, receiver, Handle<Map>::null(), true); |
| 7971 } | 7916 } |
| 7972 | 7917 |
| 7973 | 7918 |
| 7974 bool HOptimizedGraphBuilder::TryInlineApiMethodCall(Call* expr, | 7919 bool HOptimizedGraphBuilder::TryInlineApiMethodCall(Call* expr, |
| 7975 HValue* receiver, | 7920 HValue* receiver, |
| 7976 Handle<Map> receiver_map) { | 7921 Handle<Map> receiver_map) { |
| 7977 return TryInlineApiCall(expr, receiver, receiver_map, false, false); | 7922 return TryInlineApiCall(expr, receiver, receiver_map, false); |
| 7978 } | 7923 } |
| 7979 | 7924 |
| 7980 bool HOptimizedGraphBuilder::TryInlineApiCall(Call* expr, | 7925 bool HOptimizedGraphBuilder::TryInlineApiCall(Call* expr, |
| 7981 HValue* receiver, | 7926 HValue* receiver, |
| 7982 Handle<Map> receiver_map, | 7927 Handle<Map> receiver_map, |
| 7983 bool drop_extra, | |
| 7984 bool is_function_call) { | 7928 bool is_function_call) { |
| 7985 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { | 7929 if (!expr->IsMonomorphic()) return false; |
| 7986 return false; | |
| 7987 } | |
| 7988 CallOptimization optimization(expr->target()); | 7930 CallOptimization optimization(expr->target()); |
| 7989 if (!optimization.is_simple_api_call()) return false; | 7931 if (!optimization.is_simple_api_call()) return false; |
| 7990 Handle<Map> holder_map; | 7932 Handle<Map> holder_map; |
| 7991 if (is_function_call) { | 7933 if (is_function_call) { |
| 7992 // Cannot embed a direct reference to the global proxy map | 7934 // Cannot embed a direct reference to the global proxy map |
| 7993 // as it maybe dropped on deserialization. | 7935 // as it maybe dropped on deserialization. |
| 7994 CHECK(!Serializer::enabled()); | 7936 CHECK(!Serializer::enabled()); |
| 7995 receiver_map = Handle<Map>( | 7937 receiver_map = Handle<Map>( |
| 7996 expr->target()->context()->global_object()->global_receiver()->map()); | 7938 expr->target()->context()->global_object()->global_receiver()->map()); |
| 7997 } | 7939 } |
| 7998 CallOptimization::HolderLookup holder_lookup = | 7940 CallOptimization::HolderLookup holder_lookup = |
| 7999 CallOptimization::kHolderNotFound; | 7941 CallOptimization::kHolderNotFound; |
| 8000 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType( | 7942 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType( |
| 8001 receiver_map, &holder_lookup); | 7943 receiver_map, &holder_lookup); |
| 8002 if (holder_lookup == CallOptimization::kHolderNotFound) return false; | 7944 if (holder_lookup == CallOptimization::kHolderNotFound) return false; |
| 8003 | 7945 |
| 8004 if (FLAG_trace_inlining) { | 7946 if (FLAG_trace_inlining) { |
| 8005 PrintF("Inlining api function "); | 7947 PrintF("Inlining api function "); |
| 8006 expr->target()->ShortPrint(); | 7948 expr->target()->ShortPrint(); |
| 8007 PrintF("\n"); | 7949 PrintF("\n"); |
| 8008 } | 7950 } |
| 8009 | 7951 |
| 7952 const int argc = expr->arguments()->length(); |
| 7953 // Includes receiver. |
| 7954 PushArgumentsFromEnvironment(argc + 1); |
| 7955 |
| 8010 // Need to ensure the chain between receiver and api_holder is intact | 7956 // Need to ensure the chain between receiver and api_holder is intact |
| 8011 AddCheckMap(receiver, receiver_map); | 7957 AddCheckMap(receiver, receiver_map); |
| 8012 if (holder_lookup == CallOptimization::kHolderFound) { | 7958 if (holder_lookup == CallOptimization::kHolderFound) { |
| 8013 AddCheckPrototypeMaps(api_holder, receiver_map); | 7959 AddCheckPrototypeMaps(api_holder, receiver_map); |
| 8014 } else { | 7960 } else { |
| 8015 ASSERT_EQ(holder_lookup, CallOptimization::kHolderIsReceiver); | 7961 ASSERT_EQ(holder_lookup, CallOptimization::kHolderIsReceiver); |
| 8016 } | 7962 } |
| 8017 | 7963 |
| 8018 // TODO(verwaest): remove. | |
| 8019 if (!is_function_call) { | |
| 8020 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | |
| 8021 } | |
| 8022 | |
| 8023 HValue* holder = NULL; | 7964 HValue* holder = NULL; |
| 8024 switch (holder_lookup) { | 7965 switch (holder_lookup) { |
| 8025 case CallOptimization::kHolderFound: | 7966 case CallOptimization::kHolderFound: |
| 8026 holder = Add<HConstant>(api_holder); | 7967 holder = Add<HConstant>(api_holder); |
| 8027 break; | 7968 break; |
| 8028 case CallOptimization::kHolderIsReceiver: | 7969 case CallOptimization::kHolderIsReceiver: |
| 8029 holder = environment()->ExpressionStackAt(expr->arguments()->length()); | 7970 holder = receiver; |
| 8030 break; | 7971 break; |
| 8031 case CallOptimization::kHolderNotFound: | 7972 case CallOptimization::kHolderNotFound: |
| 8032 UNREACHABLE(); | 7973 UNREACHABLE(); |
| 8033 break; | 7974 break; |
| 8034 } | 7975 } |
| 8035 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); | 7976 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); |
| 8036 Handle<Object> call_data_obj(api_call_info->data(), isolate()); | 7977 Handle<Object> call_data_obj(api_call_info->data(), isolate()); |
| 8037 bool call_data_is_undefined = call_data_obj->IsUndefined(); | 7978 bool call_data_is_undefined = call_data_obj->IsUndefined(); |
| 8038 HValue* call_data = Add<HConstant>(call_data_obj); | 7979 HValue* call_data = Add<HConstant>(call_data_obj); |
| 8039 ApiFunction fun(v8::ToCData<Address>(api_call_info->callback())); | 7980 ApiFunction fun(v8::ToCData<Address>(api_call_info->callback())); |
| 8040 ExternalReference ref = ExternalReference(&fun, | 7981 ExternalReference ref = ExternalReference(&fun, |
| 8041 ExternalReference::DIRECT_API_CALL, | 7982 ExternalReference::DIRECT_API_CALL, |
| 8042 isolate()); | 7983 isolate()); |
| 8043 HValue* api_function_address = Add<HConstant>(ExternalReference(ref)); | 7984 HValue* api_function_address = Add<HConstant>(ExternalReference(ref)); |
| 8044 | 7985 |
| 8045 HValue* op_vals[] = { | 7986 HValue* op_vals[] = { |
| 8046 // callee | 7987 // callee |
| 8047 Add<HConstant>(expr->target()), | 7988 Add<HConstant>(expr->target()), |
| 8048 call_data, | 7989 call_data, |
| 8049 holder, | 7990 holder, |
| 8050 api_function_address, | 7991 api_function_address, |
| 8051 context() | 7992 context() |
| 8052 }; | 7993 }; |
| 8053 | 7994 |
| 8054 const int argc = expr->arguments()->length(); | |
| 8055 // Includes receiver. | |
| 8056 PushArgumentsFromEnvironment(argc + 1); | |
| 8057 | |
| 8058 CallInterfaceDescriptor* descriptor = | 7995 CallInterfaceDescriptor* descriptor = |
| 8059 isolate()->call_descriptor(Isolate::ApiFunctionCall); | 7996 isolate()->call_descriptor(Isolate::ApiFunctionCall); |
| 8060 | 7997 |
| 8061 CallApiFunctionStub stub(true, call_data_is_undefined, argc); | 7998 CallApiFunctionStub stub(true, call_data_is_undefined, argc); |
| 8062 Handle<Code> code = stub.GetCode(isolate()); | 7999 Handle<Code> code = stub.GetCode(isolate()); |
| 8063 HConstant* code_value = Add<HConstant>(code); | 8000 HConstant* code_value = Add<HConstant>(code); |
| 8064 | 8001 |
| 8065 ASSERT((sizeof(op_vals) / kPointerSize) == | 8002 ASSERT((sizeof(op_vals) / kPointerSize) == |
| 8066 descriptor->environment_length()); | 8003 descriptor->environment_length()); |
| 8067 | 8004 |
| 8068 HInstruction* call = New<HCallWithDescriptor>( | 8005 HInstruction* call = New<HCallWithDescriptor>( |
| 8069 code_value, argc + 1, descriptor, | 8006 code_value, argc + 1, descriptor, |
| 8070 Vector<HValue*>(op_vals, descriptor->environment_length())); | 8007 Vector<HValue*>(op_vals, descriptor->environment_length())); |
| 8071 | 8008 |
| 8072 if (drop_extra) Drop(1); // Drop function. | 8009 Drop(1); // Drop function. |
| 8073 ast_context()->ReturnInstruction(call, expr->id()); | 8010 ast_context()->ReturnInstruction(call, expr->id()); |
| 8074 return true; | 8011 return true; |
| 8075 } | 8012 } |
| 8076 | 8013 |
| 8077 | 8014 |
| 8078 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) { | 8015 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) { |
| 8079 Expression* callee = expr->expression(); | 8016 ASSERT(expr->expression()->IsProperty()); |
| 8080 Property* prop = callee->AsProperty(); | |
| 8081 ASSERT(prop != NULL); | |
| 8082 | 8017 |
| 8083 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { | 8018 if (!expr->IsMonomorphic()) { |
| 8084 return false; | 8019 return false; |
| 8085 } | 8020 } |
| 8086 Handle<Map> function_map = expr->GetReceiverTypes()->first(); | 8021 Handle<Map> function_map = expr->GetReceiverTypes()->first(); |
| 8087 if (function_map->instance_type() != JS_FUNCTION_TYPE || | 8022 if (function_map->instance_type() != JS_FUNCTION_TYPE || |
| 8088 !expr->target()->shared()->HasBuiltinFunctionId() || | 8023 !expr->target()->shared()->HasBuiltinFunctionId() || |
| 8089 expr->target()->shared()->builtin_function_id() != kFunctionApply) { | 8024 expr->target()->shared()->builtin_function_id() != kFunctionApply) { |
| 8090 return false; | 8025 return false; |
| 8091 } | 8026 } |
| 8092 | 8027 |
| 8093 if (current_info()->scope()->arguments() == NULL) return false; | 8028 if (current_info()->scope()->arguments() == NULL) return false; |
| 8094 | 8029 |
| 8095 ZoneList<Expression*>* args = expr->arguments(); | 8030 ZoneList<Expression*>* args = expr->arguments(); |
| 8096 if (args->length() != 2) return false; | 8031 if (args->length() != 2) return false; |
| 8097 | 8032 |
| 8098 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); | 8033 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); |
| 8099 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; | 8034 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; |
| 8100 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); | 8035 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); |
| 8101 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; | 8036 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; |
| 8102 | 8037 |
| 8103 // Found pattern f.apply(receiver, arguments). | 8038 // Found pattern f.apply(receiver, arguments). |
| 8104 CHECK_ALIVE_OR_RETURN(VisitForValue(prop->obj()), true); | |
| 8105 HValue* function = Top(); | |
| 8106 | |
| 8107 AddCheckConstantFunction(expr->holder(), function, function_map); | |
| 8108 | |
| 8109 CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true); | 8039 CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true); |
| 8110 HValue* receiver = Pop(); | 8040 HValue* receiver = Pop(); // receiver |
| 8111 | 8041 HValue* function = Pop(); // f |
| 8112 Drop(1); // Pop the function. | 8042 Drop(1); // apply |
| 8113 | 8043 |
| 8114 if (function_state()->outer() == NULL) { | 8044 if (function_state()->outer() == NULL) { |
| 8115 HInstruction* elements = Add<HArgumentsElements>(false); | 8045 HInstruction* elements = Add<HArgumentsElements>(false); |
| 8116 HInstruction* length = Add<HArgumentsLength>(elements); | 8046 HInstruction* length = Add<HArgumentsLength>(elements); |
| 8117 HValue* wrapped_receiver = BuildWrapReceiver(receiver, function); | 8047 HValue* wrapped_receiver = BuildWrapReceiver(receiver, function); |
| 8118 HInstruction* result = New<HApplyArguments>(function, | 8048 HInstruction* result = New<HApplyArguments>(function, |
| 8119 wrapped_receiver, | 8049 wrapped_receiver, |
| 8120 length, | 8050 length, |
| 8121 elements); | 8051 elements); |
| 8122 ast_context()->ReturnInstruction(result, expr->id()); | 8052 ast_context()->ReturnInstruction(result, expr->id()); |
| 8123 return true; | 8053 return true; |
| 8124 } else { | 8054 } else { |
| 8125 // We are inside inlined function and we know exactly what is inside | 8055 // We are inside inlined function and we know exactly what is inside |
| 8126 // arguments object. But we need to be able to materialize at deopt. | 8056 // arguments object. But we need to be able to materialize at deopt. |
| 8127 ASSERT_EQ(environment()->arguments_environment()->parameter_count(), | 8057 ASSERT_EQ(environment()->arguments_environment()->parameter_count(), |
| 8128 function_state()->entry()->arguments_object()->arguments_count()); | 8058 function_state()->entry()->arguments_object()->arguments_count()); |
| 8129 HArgumentsObject* args = function_state()->entry()->arguments_object(); | 8059 HArgumentsObject* args = function_state()->entry()->arguments_object(); |
| 8130 const ZoneList<HValue*>* arguments_values = args->arguments_values(); | 8060 const ZoneList<HValue*>* arguments_values = args->arguments_values(); |
| 8131 int arguments_count = arguments_values->length(); | 8061 int arguments_count = arguments_values->length(); |
| 8062 Push(function); |
| 8132 Push(BuildWrapReceiver(receiver, function)); | 8063 Push(BuildWrapReceiver(receiver, function)); |
| 8133 for (int i = 1; i < arguments_count; i++) { | 8064 for (int i = 1; i < arguments_count; i++) { |
| 8134 Push(arguments_values->at(i)); | 8065 Push(arguments_values->at(i)); |
| 8135 } | 8066 } |
| 8136 | 8067 |
| 8137 Handle<JSFunction> known_function; | 8068 Handle<JSFunction> known_function; |
| 8138 if (function->IsConstant() && | 8069 if (function->IsConstant() && |
| 8139 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { | 8070 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { |
| 8140 known_function = Handle<JSFunction>::cast( | 8071 known_function = Handle<JSFunction>::cast( |
| 8141 HConstant::cast(function)->handle(isolate())); | 8072 HConstant::cast(function)->handle(isolate())); |
| 8142 int args_count = arguments_count - 1; // Excluding receiver. | 8073 int args_count = arguments_count - 1; // Excluding receiver. |
| 8143 if (TryInlineApply(known_function, expr, args_count)) return true; | 8074 if (TryInlineApply(known_function, expr, args_count)) return true; |
| 8144 } | 8075 } |
| 8145 | 8076 |
| 8146 Drop(arguments_count - 1); | 8077 PushArgumentsFromEnvironment(arguments_count); |
| 8147 Push(Add<HPushArgument>(Pop())); | 8078 HInvokeFunction* call = New<HInvokeFunction>( |
| 8148 for (int i = 1; i < arguments_count; i++) { | 8079 function, known_function, arguments_count); |
| 8149 Push(Add<HPushArgument>(arguments_values->at(i))); | 8080 Drop(1); // Function. |
| 8150 } | |
| 8151 | |
| 8152 HInvokeFunction* call = New<HInvokeFunction>(function, | |
| 8153 known_function, | |
| 8154 arguments_count); | |
| 8155 Drop(arguments_count); | |
| 8156 ast_context()->ReturnInstruction(call, expr->id()); | 8081 ast_context()->ReturnInstruction(call, expr->id()); |
| 8157 return true; | 8082 return true; |
| 8158 } | 8083 } |
| 8159 } | 8084 } |
| 8160 | 8085 |
| 8161 | 8086 |
| 8162 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function, | 8087 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function, |
| 8163 Handle<JSFunction> target) { | 8088 Handle<JSFunction> target) { |
| 8164 SharedFunctionInfo* shared = target->shared(); | 8089 SharedFunctionInfo* shared = target->shared(); |
| 8165 if (shared->is_classic_mode() && !shared->native()) { | 8090 if (shared->is_classic_mode() && !shared->native()) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 8177 void HOptimizedGraphBuilder::VisitCall(Call* expr) { | 8102 void HOptimizedGraphBuilder::VisitCall(Call* expr) { |
| 8178 ASSERT(!HasStackOverflow()); | 8103 ASSERT(!HasStackOverflow()); |
| 8179 ASSERT(current_block() != NULL); | 8104 ASSERT(current_block() != NULL); |
| 8180 ASSERT(current_block()->HasPredecessor()); | 8105 ASSERT(current_block()->HasPredecessor()); |
| 8181 Expression* callee = expr->expression(); | 8106 Expression* callee = expr->expression(); |
| 8182 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 8107 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
| 8183 HInstruction* call = NULL; | 8108 HInstruction* call = NULL; |
| 8184 | 8109 |
| 8185 Property* prop = callee->AsProperty(); | 8110 Property* prop = callee->AsProperty(); |
| 8186 if (prop != NULL) { | 8111 if (prop != NULL) { |
| 8187 if (!prop->key()->IsPropertyName()) { | 8112 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 8188 // Keyed function call. | 8113 HValue* receiver = Top(); |
| 8189 CHECK_ALIVE(VisitForValue(prop->obj())); | |
| 8190 CHECK_ALIVE(VisitForValue(prop->key())); | |
| 8191 | 8114 |
| 8192 // Push receiver and key like the non-optimized code generator expects it. | 8115 SmallMapList* types; |
| 8193 HValue* key = Pop(); | 8116 ComputeReceiverTypes(expr, receiver, &types); |
| 8194 HValue* receiver = Pop(); | |
| 8195 Push(key); | |
| 8196 Push(Add<HPushArgument>(receiver)); | |
| 8197 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | |
| 8198 | 8117 |
| 8199 if (expr->IsMonomorphic()) { | 8118 if (prop->key()->IsPropertyName() && types->length() > 0) { |
| 8200 BuildCheckHeapObject(receiver); | 8119 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
| 8201 ElementsKind kind = expr->KeyedArrayCallIsHoley() | 8120 PropertyAccessInfo info(this, IC::MapToType(types->first()), name); |
| 8202 ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS; | 8121 if (!info.CanLoadAsMonomorphic(types)) { |
| 8203 | 8122 HandlePolymorphicCallNamed(expr, receiver, types, name); |
| 8204 Handle<Map> map(isolate()->get_initial_js_array_map(kind)); | 8123 return; |
| 8205 | |
| 8206 HValue* function = BuildMonomorphicElementAccess( | |
| 8207 receiver, key, NULL, NULL, map, false, STANDARD_STORE); | |
| 8208 | |
| 8209 call = New<HCallFunction>(function, argument_count); | |
| 8210 } else { | |
| 8211 call = NewCallKeyed(key, argument_count); | |
| 8212 } | 8124 } |
| 8213 Drop(argument_count + 1); // 1 is the key. | |
| 8214 return ast_context()->ReturnInstruction(call, expr->id()); | |
| 8215 } | 8125 } |
| 8216 | 8126 |
| 8217 // Named function call. | 8127 HValue* key = NULL; |
| 8218 if (TryCallApply(expr)) return; | 8128 if (!prop->key()->IsPropertyName()) { |
| 8219 | 8129 CHECK_ALIVE(VisitForValue(prop->key())); |
| 8220 CHECK_ALIVE(VisitForValue(prop->obj())); | 8130 key = Pop(); |
| 8221 CHECK_ALIVE(VisitExpressions(expr->arguments())); | |
| 8222 | |
| 8223 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | |
| 8224 HValue* receiver = | |
| 8225 environment()->ExpressionStackAt(expr->arguments()->length()); | |
| 8226 | |
| 8227 SmallMapList* types; | |
| 8228 bool was_monomorphic = expr->IsMonomorphic(); | |
| 8229 bool monomorphic = ComputeReceiverTypes(expr, receiver, &types); | |
| 8230 if (!was_monomorphic && monomorphic) { | |
| 8231 monomorphic = expr->ComputeTarget(types->first(), name); | |
| 8232 } | 8131 } |
| 8233 | 8132 |
| 8234 if (monomorphic) { | 8133 CHECK_ALIVE(PushLoad(prop, receiver, key)); |
| 8235 Handle<Map> map = types->first(); | 8134 HValue* function = Pop(); |
| 8236 if (TryInlineBuiltinMethodCall(expr, receiver, map, expr->check_type())) { | 8135 |
| 8136 // Push the function under the receiver. |
| 8137 environment()->SetExpressionStackAt(0, function); |
| 8138 |
| 8139 Push(receiver); |
| 8140 |
| 8141 if (function->IsConstant() && |
| 8142 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { |
| 8143 Handle<JSFunction> known_function = Handle<JSFunction>::cast( |
| 8144 HConstant::cast(function)->handle(isolate())); |
| 8145 expr->set_target(known_function); |
| 8146 |
| 8147 if (TryCallApply(expr)) return; |
| 8148 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 8149 |
| 8150 Handle<Map> map = types->length() == 1 ? types->first() : Handle<Map>(); |
| 8151 if (TryInlineBuiltinMethodCall(expr, receiver, map)) { |
| 8237 if (FLAG_trace_inlining) { | 8152 if (FLAG_trace_inlining) { |
| 8238 PrintF("Inlining builtin "); | 8153 PrintF("Inlining builtin "); |
| 8239 expr->target()->ShortPrint(); | 8154 known_function->ShortPrint(); |
| 8240 PrintF("\n"); | 8155 PrintF("\n"); |
| 8241 } | 8156 } |
| 8242 return; | 8157 return; |
| 8243 } | 8158 } |
| 8244 if (TryInlineApiMethodCall(expr, receiver, map)) return; | 8159 if (TryInlineApiMethodCall(expr, receiver, map)) return; |
| 8245 | 8160 |
| 8246 if (expr->check_type() != RECEIVER_MAP_CHECK) { | 8161 // Wrap the receiver if necessary. |
| 8247 call = NewCallNamed(name, argument_count); | 8162 if (NeedsWrappingFor(IC::MapToType(types->first()), known_function)) { |
| 8248 PushArgumentsFromEnvironment(argument_count); | 8163 // Since HWrapReceiver currently cannot actually wrap numbers and |
| 8164 // strings, use the regular CallFunctionStub for method calls to wrap |
| 8165 // the receiver. |
| 8166 // TODO(verwaest): Support creation of value wrappers directly in |
| 8167 // HWrapReceiver. |
| 8168 call = New<HCallFunction>( |
| 8169 function, argument_count, WRAP_AND_CALL); |
| 8170 } else if (TryInlineCall(expr)) { |
| 8171 return; |
| 8249 } else { | 8172 } else { |
| 8250 AddCheckConstantFunction(expr->holder(), receiver, map); | 8173 call = BuildCallConstantFunction(known_function, argument_count); |
| 8251 | |
| 8252 if (TryInlineCall(expr)) return; | |
| 8253 call = BuildCallConstantFunction(expr->target(), argument_count); | |
| 8254 PushArgumentsFromEnvironment(argument_count); | |
| 8255 } | 8174 } |
| 8256 } else if (types != NULL && types->length() > 1) { | |
| 8257 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); | |
| 8258 HandlePolymorphicCallNamed(expr, receiver, types, name); | |
| 8259 return; | |
| 8260 | 8175 |
| 8261 } else { | 8176 } else { |
| 8262 call = NewCallNamed(name, argument_count); | 8177 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 8263 PushArgumentsFromEnvironment(argument_count); | 8178 CallFunctionFlags flags = receiver->type().IsJSObject() |
| 8179 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD; |
| 8180 call = New<HCallFunction>(function, argument_count, flags); |
| 8264 } | 8181 } |
| 8182 PushArgumentsFromEnvironment(argument_count); |
| 8183 |
| 8265 } else { | 8184 } else { |
| 8266 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 8185 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 8267 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { | 8186 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { |
| 8268 return Bailout(kPossibleDirectCallToEval); | 8187 return Bailout(kPossibleDirectCallToEval); |
| 8269 } | 8188 } |
| 8270 | 8189 |
| 8271 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); | 8190 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); |
| 8272 if (global_call) { | 8191 if (global_call) { |
| 8273 Variable* var = proxy->var(); | 8192 Variable* var = proxy->var(); |
| 8274 bool known_global_function = false; | 8193 bool known_global_function = false; |
| 8275 // If there is a global property cell for the name at compile time and | 8194 // If there is a global property cell for the name at compile time and |
| 8276 // access check is not enabled we assume that the function will not change | 8195 // access check is not enabled we assume that the function will not change |
| 8277 // and generate optimized code for calling the function. | 8196 // and generate optimized code for calling the function. |
| 8278 LookupResult lookup(isolate()); | 8197 LookupResult lookup(isolate()); |
| 8279 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); | 8198 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); |
| 8280 if (type == kUseCell && | 8199 if (type == kUseCell && |
| 8281 !current_info()->global_object()->IsAccessCheckNeeded()) { | 8200 !current_info()->global_object()->IsAccessCheckNeeded()) { |
| 8282 Handle<GlobalObject> global(current_info()->global_object()); | 8201 Handle<GlobalObject> global(current_info()->global_object()); |
| 8283 known_global_function = expr->ComputeGlobalTarget(global, &lookup); | 8202 known_global_function = expr->ComputeGlobalTarget(global, &lookup); |
| 8284 } | 8203 } |
| 8204 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 8205 HValue* function = Top(); |
| 8285 if (known_global_function) { | 8206 if (known_global_function) { |
| 8286 // Push the global object instead of the global receiver because | 8207 Add<HCheckValue>(function, expr->target()); |
| 8287 // code generated by the full code generator expects it. | |
| 8288 HValue* global_object = Add<HLoadNamedField>( | |
| 8289 context(), static_cast<HValue*>(NULL), | |
| 8290 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); | |
| 8291 Push(global_object); | |
| 8292 | 8208 |
| 8209 // Placeholder for the receiver. |
| 8210 Push(graph()->GetConstantUndefined()); |
| 8293 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 8211 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 8294 | 8212 |
| 8295 CHECK_ALIVE(VisitForValue(expr->expression())); | |
| 8296 HValue* function = Pop(); | |
| 8297 Add<HCheckValue>(function, expr->target()); | |
| 8298 | |
| 8299 // Patch the global object on the stack by the expected receiver. | 8213 // Patch the global object on the stack by the expected receiver. |
| 8300 HValue* receiver = ImplicitReceiverFor(function, expr->target()); | 8214 HValue* receiver = ImplicitReceiverFor(function, expr->target()); |
| 8301 const int receiver_index = argument_count - 1; | 8215 const int receiver_index = argument_count - 1; |
| 8302 environment()->SetExpressionStackAt(receiver_index, receiver); | 8216 environment()->SetExpressionStackAt(receiver_index, receiver); |
| 8303 | 8217 |
| 8304 if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop. | 8218 if (TryInlineBuiltinFunctionCall(expr)) { |
| 8305 if (FLAG_trace_inlining) { | 8219 if (FLAG_trace_inlining) { |
| 8306 PrintF("Inlining builtin "); | 8220 PrintF("Inlining builtin "); |
| 8307 expr->target()->ShortPrint(); | 8221 expr->target()->ShortPrint(); |
| 8308 PrintF("\n"); | 8222 PrintF("\n"); |
| 8309 } | 8223 } |
| 8310 return; | 8224 return; |
| 8311 } | 8225 } |
| 8312 if (TryInlineApiFunctionCall(expr, receiver, false)) return; | 8226 if (TryInlineApiFunctionCall(expr, receiver)) return; |
| 8313 if (TryInlineCall(expr)) return; | 8227 if (TryInlineCall(expr)) return; |
| 8314 | 8228 |
| 8315 if (expr->target().is_identical_to(current_info()->closure())) { | 8229 PushArgumentsFromEnvironment(argument_count); |
| 8316 graph()->MarkRecursive(); | |
| 8317 } | |
| 8318 | |
| 8319 call = BuildCallConstantFunction(expr->target(), argument_count); | 8230 call = BuildCallConstantFunction(expr->target(), argument_count); |
| 8320 PushArgumentsFromEnvironment(argument_count); | |
| 8321 } else { | 8231 } else { |
| 8322 HValue* receiver = Add<HLoadNamedField>( | 8232 Push(Add<HPushArgument>(graph()->GetConstantUndefined())); |
| 8323 context(), static_cast<HValue*>(NULL), | |
| 8324 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); | |
| 8325 Push(Add<HPushArgument>(receiver)); | |
| 8326 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 8233 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
| 8327 | 8234 call = New<HCallFunction>(function, argument_count); |
| 8328 call = NewCallNamed(var->name(), argument_count); | |
| 8329 Drop(argument_count); | 8235 Drop(argument_count); |
| 8330 } | 8236 } |
| 8331 | 8237 |
| 8332 } else if (expr->IsMonomorphic()) { | 8238 } else if (expr->IsMonomorphic()) { |
| 8333 // The function is on the stack in the unoptimized code during | 8239 // The function is on the stack in the unoptimized code during |
| 8334 // evaluation of the arguments. | 8240 // evaluation of the arguments. |
| 8335 CHECK_ALIVE(VisitForValue(expr->expression())); | 8241 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 8336 HValue* function = Top(); | 8242 HValue* function = Top(); |
| 8337 | 8243 |
| 8338 Add<HCheckValue>(function, expr->target()); | 8244 Add<HCheckValue>(function, expr->target()); |
| 8339 | 8245 |
| 8340 HValue* receiver = ImplicitReceiverFor(function, expr->target()); | 8246 Push(graph()->GetConstantUndefined()); |
| 8341 Push(receiver); | |
| 8342 | |
| 8343 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 8247 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 8344 | 8248 |
| 8345 if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function. | 8249 HValue* receiver = ImplicitReceiverFor(function, expr->target()); |
| 8250 const int receiver_index = argument_count - 1; |
| 8251 environment()->SetExpressionStackAt(receiver_index, receiver); |
| 8252 |
| 8253 if (TryInlineBuiltinFunctionCall(expr)) { |
| 8346 if (FLAG_trace_inlining) { | 8254 if (FLAG_trace_inlining) { |
| 8347 PrintF("Inlining builtin "); | 8255 PrintF("Inlining builtin "); |
| 8348 expr->target()->ShortPrint(); | 8256 expr->target()->ShortPrint(); |
| 8349 PrintF("\n"); | 8257 PrintF("\n"); |
| 8350 } | 8258 } |
| 8351 return; | 8259 return; |
| 8352 } | 8260 } |
| 8353 if (TryInlineApiFunctionCall(expr, receiver, true)) return; | 8261 if (TryInlineApiFunctionCall(expr, receiver)) return; |
| 8354 | 8262 |
| 8355 if (TryInlineCall(expr, true)) { // Drop function from environment. | 8263 if (TryInlineCall(expr)) return; |
| 8356 return; | 8264 |
| 8357 } else { | 8265 call = PreProcessCall(New<HInvokeFunction>( |
| 8358 call = PreProcessCall(New<HInvokeFunction>(function, expr->target(), | 8266 function, expr->target(), argument_count)); |
| 8359 argument_count)); | |
| 8360 Drop(1); // The function. | |
| 8361 } | |
| 8362 | 8267 |
| 8363 } else { | 8268 } else { |
| 8364 CHECK_ALIVE(VisitForValue(expr->expression())); | 8269 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 8365 HValue* function = Top(); | 8270 HValue* function = Top(); |
| 8366 HValue* receiver = graph()->GetConstantUndefined(); | 8271 HValue* receiver = graph()->GetConstantUndefined(); |
| 8367 Push(Add<HPushArgument>(receiver)); | 8272 Push(Add<HPushArgument>(receiver)); |
| 8368 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 8273 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
| 8369 call = New<HCallFunction>( | 8274 call = New<HCallFunction>(function, argument_count); |
| 8370 function, argument_count, NORMAL_CONTEXTUAL_CALL); | 8275 Drop(argument_count); |
| 8371 Drop(argument_count + 1); | |
| 8372 } | 8276 } |
| 8373 } | 8277 } |
| 8374 | 8278 |
| 8279 Drop(1); // Drop the function. |
| 8375 return ast_context()->ReturnInstruction(call, expr->id()); | 8280 return ast_context()->ReturnInstruction(call, expr->id()); |
| 8376 } | 8281 } |
| 8377 | 8282 |
| 8378 | 8283 |
| 8379 void HOptimizedGraphBuilder::BuildInlinedCallNewArray(CallNew* expr) { | 8284 void HOptimizedGraphBuilder::BuildInlinedCallNewArray(CallNew* expr) { |
| 8380 NoObservableSideEffectsScope no_effects(this); | 8285 NoObservableSideEffectsScope no_effects(this); |
| 8381 | 8286 |
| 8382 int argument_count = expr->arguments()->length(); | 8287 int argument_count = expr->arguments()->length(); |
| 8383 // We should at least have the constructor on the expression stack. | 8288 // We should at least have the constructor on the expression stack. |
| 8384 HValue* constructor = environment()->ExpressionStackAt(argument_count); | 8289 HValue* constructor = environment()->ExpressionStackAt(argument_count); |
| (...skipping 3075 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11460 if (ShouldProduceTraceOutput()) { | 11365 if (ShouldProduceTraceOutput()) { |
| 11461 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11366 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 11462 } | 11367 } |
| 11463 | 11368 |
| 11464 #ifdef DEBUG | 11369 #ifdef DEBUG |
| 11465 graph_->Verify(false); // No full verify. | 11370 graph_->Verify(false); // No full verify. |
| 11466 #endif | 11371 #endif |
| 11467 } | 11372 } |
| 11468 | 11373 |
| 11469 } } // namespace v8::internal | 11374 } } // namespace v8::internal |
| OLD | NEW |