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

Side by Side Diff: src/hydrogen.cc

Issue 138453002: Revert "Polymorphic named calls optimized for the case of repetitive call targets." for now because… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 11 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 | « no previous file | no next file » | 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 6837 matching lines...) Expand 10 before | Expand all | Expand 10 after
6848 6848
6849 6849
6850 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( 6850 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
6851 Call* expr, 6851 Call* expr,
6852 HValue* receiver, 6852 HValue* receiver,
6853 SmallMapList* types, 6853 SmallMapList* types,
6854 Handle<String> name) { 6854 Handle<String> name) {
6855 if (TryCallPolymorphicAsMonomorphic(expr, receiver, types, name)) return; 6855 if (TryCallPolymorphicAsMonomorphic(expr, receiver, types, name)) return;
6856 6856
6857 int argument_count = expr->arguments()->length() + 1; // Includes receiver. 6857 int argument_count = expr->arguments()->length() + 1; // Includes receiver.
6858 HBasicBlock* join = NULL;
6859 FunctionSorter order[kMaxCallPolymorphism];
6860 int ordered_functions = 0;
6858 6861
6859 Handle<Map> initial_string_map( 6862 Handle<Map> initial_string_map(
6860 isolate()->native_context()->string_function()->initial_map()); 6863 isolate()->native_context()->string_function()->initial_map());
6861 Handle<Map> string_marker_map( 6864 Handle<Map> string_marker_map(
6862 JSObject::cast(initial_string_map->prototype())->map()); 6865 JSObject::cast(initial_string_map->prototype())->map());
6863 Handle<Map> initial_number_map( 6866 Handle<Map> initial_number_map(
6864 isolate()->native_context()->number_function()->initial_map()); 6867 isolate()->native_context()->number_function()->initial_map());
6865 Handle<Map> number_marker_map( 6868 Handle<Map> number_marker_map(
6866 JSObject::cast(initial_number_map->prototype())->map()); 6869 JSObject::cast(initial_number_map->prototype())->map());
6867 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); 6870 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
6868 6871
6869 bool handle_smi = false; 6872 bool handle_smi = false;
6870 6873
6871 // A map from functions to a set of receivers' maps.
6872 struct FuncMapEntry {
6873 Handle<JSFunction> func;
6874 SmallMapList maps;
6875 };
6876 FuncMapEntry func_map[kMaxCallPolymorphism];
6877 FunctionSorter order[kMaxCallPolymorphism];
6878 int func_count = 0;
6879 int maps_count = 0;
6880
6881 for (int i = 0; 6874 for (int i = 0;
6882 i < types->length() && func_count < kMaxCallPolymorphism; 6875 i < types->length() && ordered_functions < kMaxCallPolymorphism;
6883 ++i) { 6876 ++i) {
6884 Handle<Map> map = types->at(i); 6877 Handle<Map> map = types->at(i);
6885 if (expr->ComputeTarget(map, name)) { 6878 if (expr->ComputeTarget(map, name)) {
6886 if (map.is_identical_to(number_marker_map)) handle_smi = true; 6879 if (map.is_identical_to(number_marker_map)) handle_smi = true;
6887 6880 order[ordered_functions++] =
6888 // Try to find the target function among known targets. 6881 FunctionSorter(i,
6889 int func_index = 0; 6882 expr->target()->shared()->profiler_ticks(),
6890 for (; func_index < func_count; ++func_index) { 6883 InliningAstSize(expr->target()),
6891 if (*func_map[func_index].func == *expr->target()) { 6884 expr->target()->shared()->SourceSize());
6892 break;
6893 }
6894 }
6895 FuncMapEntry* entry = &func_map[func_index];
6896 if (func_index == func_count) {
6897 // Entry not found, "allocate" it.
6898 entry->func = expr->target();
6899 entry->maps.Reserve(types->length() - maps_count, zone());
6900 order[func_index] =
6901 FunctionSorter(func_index,
6902 entry->func->shared()->profiler_ticks(),
6903 InliningAstSize(entry->func),
6904 entry->func->shared()->SourceSize());
6905 ++func_count;
6906 }
6907 entry->maps.Add(map, zone());
6908 ++maps_count;
6909 } 6885 }
6910 } 6886 }
6911 6887
6912 std::sort(order, order + func_count); 6888 std::sort(order, order + ordered_functions);
6913 6889
6914 HBasicBlock* number_block = NULL; 6890 HBasicBlock* number_block = NULL;
6915 HBasicBlock* join = NULL;
6916 6891
6917 if (func_count > 0) { 6892 for (int fn = 0; fn < ordered_functions; ++fn) {
6918 // Only needed once. 6893 int i = order[fn].index();
6919 join = graph()->CreateBasicBlock(); 6894 Handle<Map> map = types->at(i);
6920 if (handle_smi) { 6895 if (fn == 0) {
6921 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); 6896 // Only needed once.
6922 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); 6897 join = graph()->CreateBasicBlock();
6923 number_block = graph()->CreateBasicBlock(); 6898 if (handle_smi) {
6924 FinishCurrentBlock( 6899 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
6925 New<HIsSmiAndBranch>(receiver, empty_smi_block, not_smi_block)); 6900 HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
6926 Goto(empty_smi_block, number_block); 6901 number_block = graph()->CreateBasicBlock();
6927 set_current_block(not_smi_block); 6902 FinishCurrentBlock(New<HIsSmiAndBranch>(
6903 receiver, empty_smi_block, not_smi_block));
6904 Goto(empty_smi_block, number_block);
6905 set_current_block(not_smi_block);
6906 } else {
6907 BuildCheckHeapObject(receiver);
6908 }
6909 }
6910 HBasicBlock* if_true = graph()->CreateBasicBlock();
6911 HBasicBlock* if_false = graph()->CreateBasicBlock();
6912 HUnaryControlInstruction* compare;
6913
6914 if (handle_smi && map.is_identical_to(number_marker_map)) {
6915 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
6916 map = initial_number_map;
6917 expr->set_number_check(
6918 Handle<JSObject>(JSObject::cast(map->prototype())));
6919 } else if (map.is_identical_to(string_marker_map)) {
6920 compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
6921 map = initial_string_map;
6922 expr->set_string_check(
6923 Handle<JSObject>(JSObject::cast(map->prototype())));
6928 } else { 6924 } else {
6929 BuildCheckHeapObject(receiver); 6925 compare = New<HCompareMap>(receiver, map, if_true, if_false);
6930 } 6926 expr->set_map_check();
6931 }
6932
6933 for (int fn = 0; fn < func_count; ++fn) {
6934 int i = order[fn].index();
6935 FuncMapEntry* func_map_entry = &func_map[i];
6936
6937 HBasicBlock* call_block = graph()->CreateBasicBlock();
6938 HBasicBlock* if_false = NULL;
6939
6940 int maps_count = func_map_entry->maps.length();
6941 for (int m = 0; m < maps_count; ++m) {
6942 Handle<Map> map = func_map_entry->maps.at(m);
6943 HBasicBlock* if_true = graph()->CreateBasicBlock();
6944 if_false = graph()->CreateBasicBlock();
6945 HUnaryControlInstruction* compare;
6946
6947 if (handle_smi && map.is_identical_to(number_marker_map)) {
6948 compare =
6949 New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
6950 map = initial_number_map;
6951 expr->set_number_check(
6952 Handle<JSObject>(JSObject::cast(map->prototype())));
6953 } else if (map.is_identical_to(string_marker_map)) {
6954 compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
6955 map = initial_string_map;
6956 expr->set_string_check(
6957 Handle<JSObject>(JSObject::cast(map->prototype())));
6958 } else {
6959 compare = New<HCompareMap>(receiver, map, if_true, if_false);
6960 expr->set_map_check();
6961 }
6962
6963 FinishCurrentBlock(compare);
6964
6965 if (expr->check_type() == NUMBER_CHECK) {
6966 Goto(if_true, number_block);
6967 if_true = number_block;
6968 number_block->SetJoinId(expr->id());
6969 }
6970 set_current_block(if_true);
6971
6972 expr->ComputeTarget(map, name);
6973 ASSERT(*expr->target() == *func_map_entry->func);
6974
6975 AddCheckPrototypeMaps(expr->holder(), map);
6976
6977 Goto(if_true, call_block);
6978
6979 set_current_block(if_false);
6980 } 6927 }
6981 6928
6982 // Generate call once for all corresponding maps. 6929 FinishCurrentBlock(compare);
6983 call_block->SetJoinId(expr->id());
6984 set_current_block(call_block);
6985 6930
6931 if (expr->check_type() == NUMBER_CHECK) {
6932 Goto(if_true, number_block);
6933 if_true = number_block;
6934 number_block->SetJoinId(expr->id());
6935 }
6936 set_current_block(if_true);
6937
6938 expr->ComputeTarget(map, name);
6939 AddCheckPrototypeMaps(expr->holder(), map);
6986 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { 6940 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
6987 Handle<JSFunction> caller = current_info()->closure(); 6941 Handle<JSFunction> caller = current_info()->closure();
6988 SmartArrayPointer<char> caller_name = 6942 SmartArrayPointer<char> caller_name =
6989 caller->shared()->DebugName()->ToCString(); 6943 caller->shared()->DebugName()->ToCString();
6990 PrintF("Trying to inline the polymorphic call to %s from %s\n", 6944 PrintF("Trying to inline the polymorphic call to %s from %s\n",
6991 name->ToCString().get(), 6945 name->ToCString().get(),
6992 caller_name.get()); 6946 caller_name.get());
6993 } 6947 }
6994 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { 6948 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) {
6995 // Trying to inline will signal that we should bailout from the 6949 // Trying to inline will signal that we should bailout from the
6996 // entire compilation by setting stack overflow on the visitor. 6950 // entire compilation by setting stack overflow on the visitor.
6997 if (HasStackOverflow()) return; 6951 if (HasStackOverflow()) return;
6998 } else { 6952 } else {
6999 HCallConstantFunction* call = 6953 HCallConstantFunction* call =
7000 New<HCallConstantFunction>(expr->target(), argument_count); 6954 New<HCallConstantFunction>(expr->target(), argument_count);
7001 PreProcessCall(call); 6955 PreProcessCall(call);
7002 AddInstruction(call); 6956 AddInstruction(call);
7003 if (!ast_context()->IsEffect()) Push(call); 6957 if (!ast_context()->IsEffect()) Push(call);
7004 } 6958 }
6959
7005 if (current_block() != NULL) Goto(join); 6960 if (current_block() != NULL) Goto(join);
7006
7007 set_current_block(if_false); 6961 set_current_block(if_false);
7008 } 6962 }
7009 6963
7010 // Finish up. Unconditionally deoptimize if we've handled all the maps we 6964 // Finish up. Unconditionally deoptimize if we've handled all the maps we
7011 // know about and do not want to handle ones we've never seen. Otherwise 6965 // know about and do not want to handle ones we've never seen. Otherwise
7012 // use a generic IC. 6966 // use a generic IC.
7013 if (maps_count == types->length() && FLAG_deoptimize_uncommon_cases) { 6967 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) {
7014 // Because the deopt may be the only path in the polymorphic call, make sure 6968 // Because the deopt may be the only path in the polymorphic call, make sure
7015 // that the environment stack matches the depth on deopt that it otherwise 6969 // that the environment stack matches the depth on deopt that it otherwise
7016 // would have had after a successful call. 6970 // would have had after a successful call.
7017 Drop(argument_count); 6971 Drop(argument_count);
7018 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); 6972 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0());
7019 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); 6973 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join);
7020 } else { 6974 } else {
7021 HCallNamed* call = New<HCallNamed>(name, argument_count); 6975 HCallNamed* call = New<HCallNamed>(name, argument_count);
7022 PreProcessCall(call); 6976 PreProcessCall(call);
7023 6977
(...skipping 3963 matching lines...) Expand 10 before | Expand all | Expand 10 after
10987 if (ShouldProduceTraceOutput()) { 10941 if (ShouldProduceTraceOutput()) {
10988 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 10942 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
10989 } 10943 }
10990 10944
10991 #ifdef DEBUG 10945 #ifdef DEBUG
10992 graph_->Verify(false); // No full verify. 10946 graph_->Verify(false); // No full verify.
10993 #endif 10947 #endif
10994 } 10948 }
10995 10949
10996 } } // namespace v8::internal 10950 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698