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* object, HValue* native_context, | |
116 HValue* thing); | |
117 void StoreCodeEntry(HValue* object, | |
118 HValue* shared_info, | |
119 HValue* undefined_value); | |
120 void InstallOptimizedClosure(HValue* object, | |
121 HValue* shared_info, | |
122 HValue* native_context, | |
123 HValue* undefined_value); | |
124 | |
115 private: | 125 private: |
116 HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder); | 126 HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder); |
117 HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder, | 127 HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder, |
118 ElementsKind kind); | 128 ElementsKind kind); |
119 | 129 |
120 SmartArrayPointer<HParameter*> parameters_; | 130 SmartArrayPointer<HParameter*> parameters_; |
121 HValue* arguments_length_; | 131 HValue* arguments_length_; |
122 CompilationInfoWithZone info_; | 132 CompilationInfoWithZone info_; |
123 CodeStubInterfaceDescriptor* descriptor_; | 133 CodeStubInterfaceDescriptor* descriptor_; |
124 HContext* context_; | 134 HContext* context_; |
(...skipping 771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
896 | 906 |
897 return value; | 907 return value; |
898 } | 908 } |
899 | 909 |
900 | 910 |
901 Handle<Code> ElementsTransitionAndStoreStub::GenerateCode() { | 911 Handle<Code> ElementsTransitionAndStoreStub::GenerateCode() { |
902 return DoGenerateCode(this); | 912 return DoGenerateCode(this); |
903 } | 913 } |
904 | 914 |
905 | 915 |
916 void CodeStubGraphBuilderBase::InstallCode(HValue* object, | |
917 HValue* native_context, | |
918 HValue* first_code_slot) { | |
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 HValue* code_entry = Add<HInnerAllocatedObject>(first_code_slot, | |
927 Code::kHeaderSize - 1); | |
928 Add<HStoreNamedField>(object, HObjectAccess::ForCodeEntryPointer(), | |
929 code_entry); | |
930 | |
931 // Now link a function into a list of optimized functions. | |
932 // No need for write barrier as JSFunction object is in the new space. | |
933 HValue* optimized_functions_list = Add<HLoadNamedField>(native_context, | |
934 HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST)); | |
935 Add<HStoreNamedField>(object, HObjectAccess::ForNextFunctionLinkPointer(), | |
936 optimized_functions_list); | |
937 | |
938 // This store is the only one that should have a write barrier. | |
939 Add<HStoreNamedField>(native_context, | |
940 HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST), | |
941 object); | |
942 } | |
943 | |
944 | |
945 void CodeStubGraphBuilderBase::StoreCodeEntry(HValue* object, | |
946 HValue* shared_info, | |
947 HValue* undefined_value) { | |
948 Add<HStoreNamedField>(object, HObjectAccess::ForNextFunctionLinkPointer(), | |
949 undefined_value); | |
950 HValue* code_offset = Add<HLoadNamedField>(shared_info, | |
951 HObjectAccess::ForCodeOffset()); | |
952 HInnerAllocatedObject* code_entry = | |
953 Add<HInnerAllocatedObject>(code_offset, Code::kHeaderSize - 1); | |
954 Add<HStoreNamedField>(object, HObjectAccess::ForCodeEntryPointer(), | |
955 code_entry); | |
956 } | |
957 | |
958 | |
959 void CodeStubGraphBuilderBase::InstallOptimizedClosure( | |
960 HValue* object, | |
961 HValue* shared_info, | |
962 HValue* native_context, | |
963 HValue* undefined_value) { | |
964 Counters* counters = isolate()->counters(); | |
965 IfBuilder is_optimized(this); | |
966 HInstruction* optimized_map = Add<HLoadNamedField>(shared_info, | |
967 HObjectAccess::ForOptimizedCodeMap()); | |
968 HValue* null_constant = Add<HConstant>(0); | |
969 is_optimized.If<HCompareObjectEqAndBranch>(optimized_map, null_constant); | |
970 is_optimized.Then(); | |
Sven Panne
2013/08/08 06:23:34
"Higher order" programming via funny formatting...
| |
971 { | |
972 StoreCodeEntry(object, shared_info, undefined_value); | |
973 } | |
974 is_optimized.Else(); | |
975 { | |
976 AddIncrementCounter(counters->fast_new_closure_try_optimized(), context()); | |
977 // optimized_map points to fixed array of 3-element entries | |
978 // (native context, optimized code, literals). | |
979 // Map must never be empty, so check the first elements. | |
980 Label install_optimized; | |
981 HValue* first_code_slot = Add<HLoadNamedField>(optimized_map, | |
982 HObjectAccess::ForFirstCodeSlot()); | |
983 HValue* first_context_slot = Add<HLoadNamedField>(optimized_map, | |
984 HObjectAccess::ForFirstContextSlot()); | |
985 IfBuilder already_in(this); | |
986 already_in.If<HCompareObjectEqAndBranch>(native_context, | |
987 first_context_slot); | |
988 already_in.Then(); | |
989 { | |
990 InstallCode(object, native_context, first_code_slot); | |
991 } | |
992 already_in.Else(); | |
993 { | |
994 HValue* shared_function_entry_length = | |
995 Add<HConstant>(SharedFunctionInfo::kEntryLength); | |
996 LoopBuilder loop_builder(this, | |
997 context(), | |
998 LoopBuilder::kPostDecrement, | |
999 shared_function_entry_length); | |
1000 HValue* array_length = Add<HLoadNamedField>(optimized_map, | |
1001 HObjectAccess::ForFixedArrayLength()); | |
1002 HValue* key = loop_builder.BeginBody(array_length, | |
1003 graph()->GetConstant0(), | |
1004 Token::GT); | |
1005 { | |
1006 // Iterate through the rest of map backwards. | |
1007 // Do not double check first entry. | |
1008 HValue* second_entry_index = | |
1009 Add<HConstant>(SharedFunctionInfo::kSecondEntryIndex); | |
1010 IfBuilder restore_check(this); | |
1011 restore_check.If<HCompareNumericAndBranch>(key, second_entry_index, | |
1012 Token::EQ); | |
1013 restore_check.Then(); | |
1014 { | |
1015 // Store the unoptimized code | |
1016 StoreCodeEntry(object, shared_info, undefined_value); | |
1017 loop_builder.Break(); | |
1018 } | |
1019 restore_check.Else(); | |
1020 { | |
1021 HValue* keyed_minus = AddInstruction(HSub::New(zone(), context(), key, | |
1022 shared_function_entry_length)); | |
1023 HInstruction* keyed_lookup = Add<HLoadKeyed>(optimized_map, | |
1024 keyed_minus, static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
1025 IfBuilder done_check(this); | |
1026 done_check.If<HCompareObjectEqAndBranch>(native_context, | |
1027 keyed_lookup); | |
1028 done_check.Then(); | |
1029 { | |
1030 // Hit: fetch the optimized code. | |
1031 HValue* keyed_plus = AddInstruction(HAdd::New(zone(), context(), | |
1032 keyed_minus, graph()->GetConstant1())); | |
1033 HValue* first_code_slot_reloaded = Add<HLoadKeyed>(optimized_map, | |
1034 keyed_plus, static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
1035 InstallCode(object, native_context, first_code_slot_reloaded); | |
1036 | |
1037 // Fall out of the loop | |
1038 loop_builder.Break(); | |
1039 } | |
1040 done_check.Else(); | |
1041 done_check.End(); | |
1042 } | |
1043 restore_check.End(); | |
1044 } | |
1045 loop_builder.EndBody(); | |
1046 } | |
1047 already_in.End(); | |
1048 } | |
1049 is_optimized.End(); | |
1050 } | |
1051 | |
1052 | |
1053 template<> | |
1054 HValue* CodeStubGraphBuilder<FastNewClosureStub>::BuildCodeStub() { | |
1055 Counters* counters = isolate()->counters(); | |
1056 Factory* factory = isolate()->factory(); | |
1057 HInstruction* empty_fixed_array = | |
1058 Add<HConstant>(factory->empty_fixed_array()); | |
1059 HInstruction* undefined_value = Add<HConstant>(factory->undefined_value()); | |
1060 HValue* shared_info = GetParameter(0); | |
1061 | |
1062 // Create a new closure from the given function info in new space | |
1063 HValue* size = Add<HConstant>(JSFunction::kSize); | |
1064 HInstruction* object = Add<HAllocate>(size, HType::JSObject(), NOT_TENURED, | |
1065 JS_FUNCTION_TYPE); | |
1066 AddIncrementCounter(counters->fast_new_closure_total(), context()); | |
1067 | |
1068 int map_index = Context::FunctionMapIndex(casted_stub()->language_mode(), | |
1069 casted_stub()->is_generator()); | |
1070 | |
1071 // Compute the function map in the current native context and set that | |
1072 // as the map of the allocated object. | |
1073 HInstruction* native_context = BuildGetNativeContext(); | |
1074 HInstruction* map_slot_value = Add<HLoadNamedField>(native_context, | |
1075 HObjectAccess::ForContextSlot(map_index)); | |
1076 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map_slot_value); | |
1077 | |
1078 // Initialize the rest of the function. We don't have to update the | |
1079 // write barrier because the allocated object is in new space. | |
1080 Add<HStoreNamedField>(object, HObjectAccess::ForPropertiesPointer(), | |
1081 empty_fixed_array); | |
1082 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | |
1083 empty_fixed_array); | |
1084 Add<HStoreNamedField>(object, HObjectAccess::ForLiteralsPointer(), | |
1085 empty_fixed_array); | |
1086 HInstruction* the_hole = Add<HConstant>(factory->the_hole_value()); | |
1087 Add<HStoreNamedField>(object, HObjectAccess::ForPrototypeOrInitialMap(), | |
1088 the_hole); | |
1089 Add<HStoreNamedField>(object, HObjectAccess::ForSharedFunctionInfoPointer(), | |
1090 shared_info); | |
1091 Add<HStoreNamedField>(object, HObjectAccess::ForFunctionContextPointer(), | |
1092 shared_info); | |
1093 Add<HStoreNamedField>(object, HObjectAccess::ForFunctionContextPointer(), | |
1094 context()); | |
1095 | |
1096 // Initialize the code pointer in the function to be the one | |
1097 // found in the shared function info object. | |
1098 // But first check if there is an optimized version for our context. | |
1099 if (FLAG_cache_optimized_code) { | |
1100 InstallOptimizedClosure(object, shared_info, native_context, | |
1101 undefined_value); | |
1102 } else { | |
1103 StoreCodeEntry(object, shared_info, undefined_value); | |
1104 } | |
1105 | |
1106 return object; | |
1107 } | |
1108 | |
1109 | |
1110 Handle<Code> FastNewClosureStub::GenerateCode() { | |
1111 return DoGenerateCode(this); | |
1112 } | |
1113 | |
1114 | |
906 } } // namespace v8::internal | 1115 } } // namespace v8::internal |
OLD | NEW |