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

Side by Side Diff: src/hydrogen.cc

Issue 118483003: Polymorphic named calls optimized for the case of repetitive call targets. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years 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 6744 matching lines...) Expand 10 before | Expand all | Expand 10 after
6755 6755
6756 6756
6757 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( 6757 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
6758 Call* expr, 6758 Call* expr,
6759 HValue* receiver, 6759 HValue* receiver,
6760 SmallMapList* types, 6760 SmallMapList* types,
6761 Handle<String> name) { 6761 Handle<String> name) {
6762 if (TryCallPolymorphicAsMonomorphic(expr, receiver, types, name)) return; 6762 if (TryCallPolymorphicAsMonomorphic(expr, receiver, types, name)) return;
6763 6763
6764 int argument_count = expr->arguments()->length() + 1; // Includes receiver. 6764 int argument_count = expr->arguments()->length() + 1; // Includes receiver.
6765 HBasicBlock* join = NULL;
6766 FunctionSorter order[kMaxCallPolymorphism];
6767 int ordered_functions = 0;
6768 6765
6769 Handle<Map> initial_string_map( 6766 Handle<Map> initial_string_map(
6770 isolate()->native_context()->string_function()->initial_map()); 6767 isolate()->native_context()->string_function()->initial_map());
6771 Handle<Map> string_marker_map( 6768 Handle<Map> string_marker_map(
6772 JSObject::cast(initial_string_map->prototype())->map()); 6769 JSObject::cast(initial_string_map->prototype())->map());
6773 Handle<Map> initial_number_map( 6770 Handle<Map> initial_number_map(
6774 isolate()->native_context()->number_function()->initial_map()); 6771 isolate()->native_context()->number_function()->initial_map());
6775 Handle<Map> number_marker_map( 6772 Handle<Map> number_marker_map(
6776 JSObject::cast(initial_number_map->prototype())->map()); 6773 JSObject::cast(initial_number_map->prototype())->map());
6777 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); 6774 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
6778 6775
6779 bool handle_smi = false; 6776 bool handle_smi = false;
6780 6777
6778 // A map from functions to a set of receivers' maps.
6779 struct FuncMapEntry {
6780 Handle<JSFunction> func;
6781 SmallMapList maps;
6782 };
6783 FuncMapEntry func_map[kMaxCallPolymorphism];
6784 FunctionSorter order[kMaxCallPolymorphism];
6785 int func_count = 0;
6786 int maps_count = 0;
6787
6781 for (int i = 0; 6788 for (int i = 0;
6782 i < types->length() && ordered_functions < kMaxCallPolymorphism; 6789 i < types->length() && func_count < kMaxCallPolymorphism;
6783 ++i) { 6790 ++i) {
6784 Handle<Map> map = types->at(i); 6791 Handle<Map> map = types->at(i);
6785 if (expr->ComputeTarget(map, name)) { 6792 if (expr->ComputeTarget(map, name)) {
6786 if (map.is_identical_to(number_marker_map)) handle_smi = true; 6793 if (map.is_identical_to(number_marker_map)) handle_smi = true;
6787 order[ordered_functions++] = 6794
6788 FunctionSorter(i, 6795 // Try to find the target function among known targets.
6789 expr->target()->shared()->profiler_ticks(), 6796 int func_index = 0;
6790 InliningAstSize(expr->target()), 6797 for (; func_index < func_count; ++func_index) {
6791 expr->target()->shared()->SourceSize()); 6798 if (*func_map[func_index].func == *expr->target()) {
6799 break;
6800 }
6801 }
6802 FuncMapEntry* entry = &func_map[func_index];
6803 if (func_index == func_count) {
6804 // Entry not found, "allocate" it.
6805 entry->func = expr->target();
6806 entry->maps.Reserve(types->length() - maps_count, zone());
6807 order[func_index] =
6808 FunctionSorter(func_index,
6809 entry->func->shared()->profiler_ticks(),
6810 InliningAstSize(entry->func),
6811 entry->func->shared()->SourceSize());
6812 ++func_count;
6813 }
6814 entry->maps.Add(map, zone());
6815 ++maps_count;
6792 } 6816 }
6793 } 6817 }
6794 6818
6795 std::sort(order, order + ordered_functions); 6819 std::sort(order, order + func_count);
6796 6820
6797 HBasicBlock* number_block = NULL; 6821 HBasicBlock* number_block = NULL;
6822 HBasicBlock* join = NULL;
6798 6823
6799 for (int fn = 0; fn < ordered_functions; ++fn) { 6824 if (func_count > 0) {
6825 // Only needed once.
6826 join = graph()->CreateBasicBlock();
6827 if (handle_smi) {
6828 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
6829 HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
6830 number_block = graph()->CreateBasicBlock();
6831 FinishCurrentBlock(New<HIsSmiAndBranch>(
6832 receiver, empty_smi_block, not_smi_block));
Toon Verwaest 2014/01/03 07:42:49 4-space indent
6833 Goto(empty_smi_block, number_block);
6834 set_current_block(not_smi_block);
6835 } else {
6836 BuildCheckHeapObject(receiver);
6837 }
6838 }
6839
6840 for (int fn = 0; fn < func_count; ++fn) {
6800 int i = order[fn].index(); 6841 int i = order[fn].index();
6801 Handle<Map> map = types->at(i); 6842 FuncMapEntry* func_map_entry = &func_map[i];
6802 if (fn == 0) { 6843
6803 // Only needed once. 6844 HBasicBlock* call_block = graph()->CreateBasicBlock();
6804 join = graph()->CreateBasicBlock(); 6845 HBasicBlock* if_false = NULL;
6805 if (handle_smi) { 6846
6806 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); 6847 int maps_count = func_map_entry->maps.length();
6807 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); 6848 for (int m = 0; m < maps_count; ++m) {
6808 number_block = graph()->CreateBasicBlock(); 6849 Handle<Map> map = func_map_entry->maps.at(m);
6809 FinishCurrentBlock(New<HIsSmiAndBranch>( 6850 HBasicBlock* if_true = graph()->CreateBasicBlock();
6810 receiver, empty_smi_block, not_smi_block)); 6851 if_false = graph()->CreateBasicBlock();
6811 Goto(empty_smi_block, number_block); 6852 HUnaryControlInstruction* compare;
6812 set_current_block(not_smi_block); 6853
6854 if (handle_smi && map.is_identical_to(number_marker_map)) {
6855 compare =
6856 New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
6857 map = initial_number_map;
6858 expr->set_number_check(
6859 Handle<JSObject>(JSObject::cast(map->prototype())));
6860 } else if (map.is_identical_to(string_marker_map)) {
6861 compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
6862 map = initial_string_map;
6863 expr->set_string_check(
6864 Handle<JSObject>(JSObject::cast(map->prototype())));
6813 } else { 6865 } else {
6814 BuildCheckHeapObject(receiver); 6866 compare = New<HCompareMap>(receiver, map, if_true, if_false);
6867 expr->set_map_check();
6815 } 6868 }
6816 }
6817 HBasicBlock* if_true = graph()->CreateBasicBlock();
6818 HBasicBlock* if_false = graph()->CreateBasicBlock();
6819 HUnaryControlInstruction* compare;
6820 6869
6821 if (handle_smi && map.is_identical_to(number_marker_map)) { 6870 FinishCurrentBlock(compare);
6822 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false); 6871
6823 map = initial_number_map; 6872 if (expr->check_type() == NUMBER_CHECK) {
6824 expr->set_number_check( 6873 Goto(if_true, number_block);
6825 Handle<JSObject>(JSObject::cast(map->prototype()))); 6874 if_true = number_block;
6826 } else if (map.is_identical_to(string_marker_map)) { 6875 number_block->SetJoinId(expr->id());
6827 compare = New<HIsStringAndBranch>(receiver, if_true, if_false); 6876 }
6828 map = initial_string_map; 6877 set_current_block(if_true);
6829 expr->set_string_check( 6878
6830 Handle<JSObject>(JSObject::cast(map->prototype()))); 6879 expr->ComputeTarget(map, name);
6831 } else { 6880 ASSERT(*expr->target() == *func_map_entry->func);
6832 compare = New<HCompareMap>(receiver, map, if_true, if_false); 6881
6833 expr->set_map_check(); 6882 AddCheckPrototypeMaps(expr->holder(), map);
6883
6884 Goto(if_true, call_block);
6885
6886 set_current_block(if_false);
6834 } 6887 }
6835 6888
6836 FinishCurrentBlock(compare); 6889 // Generate call once for all corresponding maps.
6890 call_block->SetJoinId(expr->id());
6891 set_current_block(call_block);
6837 6892
6838 if (expr->check_type() == NUMBER_CHECK) {
6839 Goto(if_true, number_block);
6840 if_true = number_block;
6841 number_block->SetJoinId(expr->id());
6842 }
6843 set_current_block(if_true);
6844
6845 expr->ComputeTarget(map, name);
6846 AddCheckPrototypeMaps(expr->holder(), map);
6847 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { 6893 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
6848 Handle<JSFunction> caller = current_info()->closure(); 6894 Handle<JSFunction> caller = current_info()->closure();
6849 SmartArrayPointer<char> caller_name = 6895 SmartArrayPointer<char> caller_name =
6850 caller->shared()->DebugName()->ToCString(); 6896 caller->shared()->DebugName()->ToCString();
6851 PrintF("Trying to inline the polymorphic call to %s from %s\n", 6897 PrintF("Trying to inline the polymorphic call to %s from %s\n",
6852 name->ToCString().get(), 6898 name->ToCString().get(),
6853 caller_name.get()); 6899 caller_name.get());
6854 } 6900 }
6855 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { 6901 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) {
6856 // Trying to inline will signal that we should bailout from the 6902 // Trying to inline will signal that we should bailout from the
6857 // entire compilation by setting stack overflow on the visitor. 6903 // entire compilation by setting stack overflow on the visitor.
6858 if (HasStackOverflow()) return; 6904 if (HasStackOverflow()) return;
6859 } else { 6905 } else {
6860 HCallConstantFunction* call = 6906 HCallConstantFunction* call =
6861 New<HCallConstantFunction>(expr->target(), argument_count); 6907 New<HCallConstantFunction>(expr->target(), argument_count);
6862 PreProcessCall(call); 6908 PreProcessCall(call);
6863 AddInstruction(call); 6909 AddInstruction(call);
6864 if (!ast_context()->IsEffect()) Push(call); 6910 if (!ast_context()->IsEffect()) Push(call);
6865 } 6911 }
6912 if (current_block() != NULL) Goto(join);
6866 6913
6867 if (current_block() != NULL) Goto(join);
6868 set_current_block(if_false); 6914 set_current_block(if_false);
6869 } 6915 }
6870 6916
6871 // Finish up. Unconditionally deoptimize if we've handled all the maps we 6917 // Finish up. Unconditionally deoptimize if we've handled all the maps we
6872 // know about and do not want to handle ones we've never seen. Otherwise 6918 // know about and do not want to handle ones we've never seen. Otherwise
6873 // use a generic IC. 6919 // use a generic IC.
6874 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { 6920 if (maps_count == types->length() && FLAG_deoptimize_uncommon_cases) {
6875 // Because the deopt may be the only path in the polymorphic call, make sure 6921 // Because the deopt may be the only path in the polymorphic call, make sure
6876 // that the environment stack matches the depth on deopt that it otherwise 6922 // that the environment stack matches the depth on deopt that it otherwise
6877 // would have had after a successful call. 6923 // would have had after a successful call.
6878 Drop(argument_count); 6924 Drop(argument_count);
6879 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); 6925 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0());
6880 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); 6926 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join);
6881 } else { 6927 } else {
6882 HCallNamed* call = New<HCallNamed>(name, argument_count); 6928 HCallNamed* call = New<HCallNamed>(name, argument_count);
6883 PreProcessCall(call); 6929 PreProcessCall(call);
6884 6930
(...skipping 3907 matching lines...) Expand 10 before | Expand all | Expand 10 after
10792 if (ShouldProduceTraceOutput()) { 10838 if (ShouldProduceTraceOutput()) {
10793 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 10839 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
10794 } 10840 }
10795 10841
10796 #ifdef DEBUG 10842 #ifdef DEBUG
10797 graph_->Verify(false); // No full verify. 10843 graph_->Verify(false); // No full verify.
10798 #endif 10844 #endif
10799 } 10845 }
10800 10846
10801 } } // namespace v8::internal 10847 } } // 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