Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(346)

Side by Side Diff: src/hydrogen.cc

Issue 148223002: Remove CallICs (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Update test262 status file Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698