Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 105 MULTIPLE | 105 MULTIPLE |
| 106 }; | 106 }; |
| 107 | 107 |
| 108 HValue* BuildArrayConstructor(ElementsKind kind, | 108 HValue* BuildArrayConstructor(ElementsKind kind, |
| 109 ContextCheckMode context_mode, | 109 ContextCheckMode context_mode, |
| 110 AllocationSiteOverrideMode override_mode, | 110 AllocationSiteOverrideMode override_mode, |
| 111 ArgumentClass argument_class); | 111 ArgumentClass argument_class); |
| 112 HValue* BuildInternalArrayConstructor(ElementsKind kind, | 112 HValue* BuildInternalArrayConstructor(ElementsKind kind, |
| 113 ArgumentClass argument_class); | 113 ArgumentClass argument_class); |
| 114 | 114 |
| 115 void InstallCode(HValue* js_function, HValue* native_context, | |
|
Michael Starzinger
2013/08/27 08:12:51
nit: Can we prefix these methods with either "Buil
mvstanton
2013/08/27 09:23:04
Done.
| |
| 116 HValue* code_object); | |
| 117 void StoreCodeEntry(HValue* js_function, HValue* shared_info, | |
| 118 HValue* undefined_value); | |
| 119 void InstallOptimizedClosure(HValue* js_function, | |
| 120 HValue* shared_info, | |
| 121 HValue* native_context, | |
| 122 HValue* undefined_value); | |
| 123 | |
| 115 private: | 124 private: |
| 116 HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder); | 125 HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder); |
| 117 HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder, | 126 HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder, |
| 118 ElementsKind kind); | 127 ElementsKind kind); |
| 119 | 128 |
| 120 SmartArrayPointer<HParameter*> parameters_; | 129 SmartArrayPointer<HParameter*> parameters_; |
| 121 HValue* arguments_length_; | 130 HValue* arguments_length_; |
| 122 CompilationInfoWithZone info_; | 131 CompilationInfoWithZone info_; |
| 123 CodeStubInterfaceDescriptor* descriptor_; | 132 CodeStubInterfaceDescriptor* descriptor_; |
| 124 HContext* context_; | 133 HContext* context_; |
| (...skipping 772 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 897 | 906 |
| 898 return value; | 907 return value; |
| 899 } | 908 } |
| 900 | 909 |
| 901 | 910 |
| 902 Handle<Code> ElementsTransitionAndStoreStub::GenerateCode() { | 911 Handle<Code> ElementsTransitionAndStoreStub::GenerateCode() { |
| 903 return DoGenerateCode(this); | 912 return DoGenerateCode(this); |
| 904 } | 913 } |
| 905 | 914 |
| 906 | 915 |
| 916 void CodeStubGraphBuilderBase::InstallCode(HValue* js_function, | |
|
Michael Starzinger
2013/08/27 08:12:51
suggestion: How about calling this method "EmitIns
mvstanton
2013/08/27 09:23:04
Good idea. Though I use "Build" instead of "Emit,"
| |
| 917 HValue* native_context, | |
| 918 HValue* code_object) { | |
| 919 Counters* counters = isolate()->counters(); | |
| 920 AddIncrementCounter(counters->fast_new_closure_install_optimized(), | |
| 921 context()); | |
| 922 | |
| 923 // TODO(fschneider): Idea: store proper code pointers in the optimized code | |
| 924 // map and either unmangle them on marking or do nothing as the whole map is | |
| 925 // discarded on major GC anyway. | |
| 926 Add<HStoreCodeEntry>(js_function, code_object); | |
| 927 | |
| 928 // Now link a function into a list of optimized functions. | |
| 929 // No need for write barrier as JSFunction object is in the new space. | |
|
Michael Starzinger
2013/08/27 08:12:51
nit: The second sentence of the comment is obsolet
mvstanton
2013/08/27 09:23:04
Done.
| |
| 930 HValue* optimized_functions_list = Add<HLoadNamedField>(native_context, | |
| 931 HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST)); | |
| 932 Add<HStoreNamedField>(js_function, | |
| 933 HObjectAccess::ForNextFunctionLinkPointer(), | |
| 934 optimized_functions_list); | |
| 935 | |
| 936 // This store is the only one that should have a write barrier. | |
| 937 Add<HStoreNamedField>(native_context, | |
| 938 HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST), | |
| 939 js_function); | |
| 940 } | |
| 941 | |
| 942 | |
| 943 void CodeStubGraphBuilderBase::StoreCodeEntry(HValue* js_function, | |
| 944 HValue* shared_info, | |
| 945 HValue* undefined_value) { | |
| 946 Add<HStoreNamedField>(js_function, | |
| 947 HObjectAccess::ForNextFunctionLinkPointer(), | |
| 948 undefined_value); | |
| 949 HValue* code_object = Add<HLoadNamedField>(shared_info, | |
| 950 HObjectAccess::ForCodeOffset()); | |
| 951 Add<HStoreCodeEntry>(js_function, code_object); | |
| 952 } | |
| 953 | |
| 954 | |
| 955 void CodeStubGraphBuilderBase::InstallOptimizedClosure( | |
|
Michael Starzinger
2013/08/27 08:12:51
suggestion: This method could be called "EmitSearc
mvstanton
2013/08/27 09:23:04
Done.
| |
| 956 HValue* js_function, | |
| 957 HValue* shared_info, | |
| 958 HValue* native_context, | |
| 959 HValue* undefined_value) { | |
| 960 Counters* counters = isolate()->counters(); | |
| 961 IfBuilder is_optimized(this); | |
| 962 HInstruction* optimized_map = Add<HLoadNamedField>(shared_info, | |
| 963 HObjectAccess::ForOptimizedCodeMap()); | |
| 964 HValue* null_constant = Add<HConstant>(0); | |
| 965 is_optimized.If<HCompareObjectEqAndBranch>(optimized_map, null_constant); | |
| 966 is_optimized.Then(); | |
| 967 { | |
| 968 StoreCodeEntry(js_function, shared_info, undefined_value); | |
| 969 } | |
| 970 is_optimized.Else(); | |
| 971 { | |
| 972 AddIncrementCounter(counters->fast_new_closure_try_optimized(), context()); | |
| 973 // optimized_map points to fixed array of 3-element entries | |
| 974 // (native context, optimized code, literals). | |
| 975 // Map must never be empty, so check the first elements. | |
| 976 Label install_optimized; | |
| 977 HValue* first_context_slot = Add<HLoadNamedField>(optimized_map, | |
| 978 HObjectAccess::ForFirstContextSlot()); | |
| 979 IfBuilder already_in(this); | |
| 980 already_in.If<HCompareObjectEqAndBranch>(native_context, | |
| 981 first_context_slot); | |
| 982 already_in.Then(); | |
| 983 { | |
| 984 HValue* code_object = Add<HLoadNamedField>(optimized_map, | |
| 985 HObjectAccess::ForFirstCodeSlot()); | |
| 986 InstallCode(js_function, native_context, code_object); | |
| 987 } | |
| 988 already_in.Else(); | |
| 989 { | |
| 990 HValue* shared_function_entry_length = | |
| 991 Add<HConstant>(SharedFunctionInfo::kEntryLength); | |
| 992 LoopBuilder loop_builder(this, | |
| 993 context(), | |
| 994 LoopBuilder::kPostDecrement, | |
| 995 shared_function_entry_length); | |
| 996 HValue* array_length = Add<HLoadNamedField>(optimized_map, | |
| 997 HObjectAccess::ForFixedArrayLength()); | |
| 998 HValue* key = loop_builder.BeginBody(array_length, | |
| 999 graph()->GetConstant0(), | |
| 1000 Token::GT); | |
| 1001 { | |
| 1002 // Iterate through the rest of map backwards. | |
| 1003 // Do not double check first entry. | |
| 1004 HValue* second_entry_index = | |
| 1005 Add<HConstant>(SharedFunctionInfo::kSecondEntryIndex); | |
| 1006 IfBuilder restore_check(this); | |
| 1007 restore_check.If<HCompareNumericAndBranch>(key, second_entry_index, | |
| 1008 Token::EQ); | |
| 1009 restore_check.Then(); | |
| 1010 { | |
| 1011 // Store the unoptimized code | |
| 1012 StoreCodeEntry(js_function, shared_info, undefined_value); | |
| 1013 loop_builder.Break(); | |
| 1014 } | |
| 1015 restore_check.Else(); | |
| 1016 { | |
| 1017 HValue* keyed_minus = AddInstruction(HSub::New(zone(), context(), key, | |
| 1018 shared_function_entry_length)); | |
| 1019 HInstruction* keyed_lookup = Add<HLoadKeyed>(optimized_map, | |
| 1020 keyed_minus, static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
| 1021 IfBuilder done_check(this); | |
| 1022 done_check.If<HCompareObjectEqAndBranch>(native_context, | |
| 1023 keyed_lookup); | |
| 1024 done_check.Then(); | |
| 1025 { | |
| 1026 // Hit: fetch the optimized code. | |
| 1027 HValue* keyed_plus = AddInstruction(HAdd::New(zone(), context(), | |
| 1028 keyed_minus, graph()->GetConstant1())); | |
| 1029 HValue* code_object = Add<HLoadKeyed>(optimized_map, | |
| 1030 keyed_plus, static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
| 1031 InstallCode(js_function, native_context, code_object); | |
| 1032 | |
| 1033 // Fall out of the loop | |
| 1034 loop_builder.Break(); | |
| 1035 } | |
| 1036 done_check.Else(); | |
| 1037 done_check.End(); | |
| 1038 } | |
| 1039 restore_check.End(); | |
| 1040 } | |
| 1041 loop_builder.EndBody(); | |
| 1042 } | |
| 1043 already_in.End(); | |
| 1044 } | |
| 1045 is_optimized.End(); | |
| 1046 } | |
| 1047 | |
| 1048 | |
| 1049 template<> | |
| 1050 HValue* CodeStubGraphBuilder<FastNewClosureStub>::BuildCodeStub() { | |
| 1051 Counters* counters = isolate()->counters(); | |
| 1052 Factory* factory = isolate()->factory(); | |
| 1053 HInstruction* empty_fixed_array = | |
| 1054 Add<HConstant>(factory->empty_fixed_array()); | |
| 1055 HInstruction* undefined_value = Add<HConstant>(factory->undefined_value()); | |
|
Michael Starzinger
2013/08/27 08:12:51
Use graph()->GetConstantUndefined() to get to the
mvstanton
2013/08/27 09:23:04
Done.
| |
| 1056 HValue* shared_info = GetParameter(0); | |
| 1057 | |
| 1058 // Create a new closure from the given function info in new space | |
| 1059 HValue* size = Add<HConstant>(JSFunction::kSize); | |
| 1060 HInstruction* js_function = Add<HAllocate>(size, HType::JSObject(), | |
| 1061 NOT_TENURED, JS_FUNCTION_TYPE); | |
| 1062 AddIncrementCounter(counters->fast_new_closure_total(), context()); | |
| 1063 | |
| 1064 int map_index = Context::FunctionMapIndex(casted_stub()->language_mode(), | |
| 1065 casted_stub()->is_generator()); | |
| 1066 | |
| 1067 // Compute the function map in the current native context and set that | |
| 1068 // as the map of the allocated object. | |
| 1069 HInstruction* native_context = BuildGetNativeContext(); | |
| 1070 HInstruction* map_slot_value = Add<HLoadNamedField>(native_context, | |
| 1071 HObjectAccess::ForContextSlot(map_index)); | |
| 1072 Add<HStoreNamedField>(js_function, HObjectAccess::ForMap(), map_slot_value); | |
| 1073 | |
| 1074 // Initialize the rest of the function. We don't have to update the | |
|
Michael Starzinger
2013/08/27 08:12:51
nit: The second sentence of the comment is obsolet
mvstanton
2013/08/27 09:23:04
Done.
| |
| 1075 // write barrier because the allocated object is in new space. | |
| 1076 Add<HStoreNamedField>(js_function, HObjectAccess::ForPropertiesPointer(), | |
| 1077 empty_fixed_array); | |
| 1078 Add<HStoreNamedField>(js_function, HObjectAccess::ForElementsPointer(), | |
| 1079 empty_fixed_array); | |
| 1080 Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(), | |
| 1081 empty_fixed_array); | |
| 1082 HInstruction* the_hole = Add<HConstant>(factory->the_hole_value()); | |
|
Michael Starzinger
2013/08/27 08:12:51
Use graph()->GetConstantHole() here instead.
mvstanton
2013/08/27 09:23:04
Done.
| |
| 1083 Add<HStoreNamedField>(js_function, HObjectAccess::ForPrototypeOrInitialMap(), | |
| 1084 the_hole); | |
| 1085 Add<HStoreNamedField>(js_function, | |
| 1086 HObjectAccess::ForSharedFunctionInfoPointer(), | |
| 1087 shared_info); | |
| 1088 Add<HStoreNamedField>(js_function, HObjectAccess::ForFunctionContextPointer(), | |
| 1089 shared_info); | |
| 1090 Add<HStoreNamedField>(js_function, HObjectAccess::ForFunctionContextPointer(), | |
| 1091 context()); | |
| 1092 | |
| 1093 // Initialize the code pointer in the function to be the one | |
| 1094 // found in the shared function info object. | |
| 1095 // But first check if there is an optimized version for our context. | |
| 1096 if (FLAG_cache_optimized_code) { | |
| 1097 InstallOptimizedClosure(js_function, shared_info, native_context, | |
| 1098 undefined_value); | |
| 1099 } else { | |
| 1100 StoreCodeEntry(js_function, shared_info, undefined_value); | |
| 1101 } | |
| 1102 | |
| 1103 return js_function; | |
| 1104 } | |
| 1105 | |
| 1106 | |
| 1107 Handle<Code> FastNewClosureStub::GenerateCode() { | |
| 1108 return DoGenerateCode(this); | |
| 1109 } | |
| 1110 | |
| 1111 | |
| 907 } } // namespace v8::internal | 1112 } } // namespace v8::internal |
| OLD | NEW |