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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 SINGLE, | 91 SINGLE, |
92 MULTIPLE | 92 MULTIPLE |
93 }; | 93 }; |
94 | 94 |
95 HValue* BuildArrayConstructor(ElementsKind kind, | 95 HValue* BuildArrayConstructor(ElementsKind kind, |
96 AllocationSiteOverrideMode override_mode, | 96 AllocationSiteOverrideMode override_mode, |
97 ArgumentClass argument_class); | 97 ArgumentClass argument_class); |
98 HValue* BuildInternalArrayConstructor(ElementsKind kind, | 98 HValue* BuildInternalArrayConstructor(ElementsKind kind, |
99 ArgumentClass argument_class); | 99 ArgumentClass argument_class); |
100 | 100 |
101 void BuildInstallOptimizedCode(HValue* js_function, HValue* native_context, | 101 // BuildCheckAndInstallOptimizedCode emits code to install the optimized |
102 HValue* code_object); | 102 // function found in the optimized code map at map_index in js_function, if |
| 103 // the function at map_index matches the given native_context. Builder is |
| 104 // left in the "Then()" state after the install. |
| 105 void BuildCheckAndInstallOptimizedCode(HValue* js_function, |
| 106 HValue* native_context, |
| 107 IfBuilder* builder, |
| 108 HValue* optimized_map, |
| 109 HValue* map_index); |
103 void BuildInstallCode(HValue* js_function, HValue* shared_info); | 110 void BuildInstallCode(HValue* js_function, HValue* shared_info); |
| 111 |
| 112 HInstruction* LoadFromOptimizedCodeMap(HValue* optimized_map, |
| 113 HValue* iterator, |
| 114 int field_offset); |
104 void BuildInstallFromOptimizedCodeMap(HValue* js_function, | 115 void BuildInstallFromOptimizedCodeMap(HValue* js_function, |
105 HValue* shared_info, | 116 HValue* shared_info, |
106 HValue* native_context); | 117 HValue* native_context); |
107 | 118 |
108 private: | 119 private: |
109 HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder); | 120 HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder); |
110 HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder, | 121 HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder, |
111 ElementsKind kind); | 122 ElementsKind kind); |
112 | 123 |
113 SmartArrayPointer<HParameter*> parameters_; | 124 SmartArrayPointer<HParameter*> parameters_; |
(...skipping 1004 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1118 | 1129 |
1119 return value; | 1130 return value; |
1120 } | 1131 } |
1121 | 1132 |
1122 | 1133 |
1123 Handle<Code> ElementsTransitionAndStoreStub::GenerateCode(Isolate* isolate) { | 1134 Handle<Code> ElementsTransitionAndStoreStub::GenerateCode(Isolate* isolate) { |
1124 return DoGenerateCode(isolate, this); | 1135 return DoGenerateCode(isolate, this); |
1125 } | 1136 } |
1126 | 1137 |
1127 | 1138 |
1128 void CodeStubGraphBuilderBase::BuildInstallOptimizedCode( | 1139 void CodeStubGraphBuilderBase::BuildCheckAndInstallOptimizedCode( |
1129 HValue* js_function, | 1140 HValue* js_function, |
1130 HValue* native_context, | 1141 HValue* native_context, |
1131 HValue* code_object) { | 1142 IfBuilder* builder, |
| 1143 HValue* optimized_map, |
| 1144 HValue* map_index) { |
| 1145 HValue* osr_ast_id_none = Add<HConstant>(BailoutId::None().ToInt()); |
| 1146 HValue* context_slot = LoadFromOptimizedCodeMap( |
| 1147 optimized_map, map_index, SharedFunctionInfo::kContextOffset); |
| 1148 HValue* osr_ast_slot = LoadFromOptimizedCodeMap( |
| 1149 optimized_map, map_index, SharedFunctionInfo::kOsrAstIdOffset); |
| 1150 builder->If<HCompareObjectEqAndBranch>(native_context, |
| 1151 context_slot); |
| 1152 builder->AndIf<HCompareObjectEqAndBranch>(osr_ast_slot, osr_ast_id_none); |
| 1153 builder->Then(); |
| 1154 HValue* code_object = LoadFromOptimizedCodeMap(optimized_map, |
| 1155 map_index, SharedFunctionInfo::kCachedCodeOffset); |
| 1156 // and the literals |
| 1157 HValue* literals = LoadFromOptimizedCodeMap(optimized_map, |
| 1158 map_index, SharedFunctionInfo::kLiteralsOffset); |
| 1159 |
1132 Counters* counters = isolate()->counters(); | 1160 Counters* counters = isolate()->counters(); |
1133 AddIncrementCounter(counters->fast_new_closure_install_optimized()); | 1161 AddIncrementCounter(counters->fast_new_closure_install_optimized()); |
1134 | 1162 |
1135 // TODO(fschneider): Idea: store proper code pointers in the optimized code | 1163 // TODO(fschneider): Idea: store proper code pointers in the optimized code |
1136 // map and either unmangle them on marking or do nothing as the whole map is | 1164 // map and either unmangle them on marking or do nothing as the whole map is |
1137 // discarded on major GC anyway. | 1165 // discarded on major GC anyway. |
1138 Add<HStoreCodeEntry>(js_function, code_object); | 1166 Add<HStoreCodeEntry>(js_function, code_object); |
| 1167 Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(), |
| 1168 literals); |
1139 | 1169 |
1140 // Now link a function into a list of optimized functions. | 1170 // Now link a function into a list of optimized functions. |
1141 HValue* optimized_functions_list = Add<HLoadNamedField>( | 1171 HValue* optimized_functions_list = Add<HLoadNamedField>( |
1142 native_context, static_cast<HValue*>(NULL), | 1172 native_context, static_cast<HValue*>(NULL), |
1143 HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST)); | 1173 HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST)); |
1144 Add<HStoreNamedField>(js_function, | 1174 Add<HStoreNamedField>(js_function, |
1145 HObjectAccess::ForNextFunctionLinkPointer(), | 1175 HObjectAccess::ForNextFunctionLinkPointer(), |
1146 optimized_functions_list); | 1176 optimized_functions_list); |
1147 | 1177 |
1148 // This store is the only one that should have a write barrier. | 1178 // This store is the only one that should have a write barrier. |
1149 Add<HStoreNamedField>(native_context, | 1179 Add<HStoreNamedField>(native_context, |
1150 HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST), | 1180 HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST), |
1151 js_function); | 1181 js_function); |
| 1182 |
| 1183 // The builder continues in the "then" after this function. |
1152 } | 1184 } |
1153 | 1185 |
1154 | 1186 |
1155 void CodeStubGraphBuilderBase::BuildInstallCode(HValue* js_function, | 1187 void CodeStubGraphBuilderBase::BuildInstallCode(HValue* js_function, |
1156 HValue* shared_info) { | 1188 HValue* shared_info) { |
1157 Add<HStoreNamedField>(js_function, | 1189 Add<HStoreNamedField>(js_function, |
1158 HObjectAccess::ForNextFunctionLinkPointer(), | 1190 HObjectAccess::ForNextFunctionLinkPointer(), |
1159 graph()->GetConstantUndefined()); | 1191 graph()->GetConstantUndefined()); |
1160 HValue* code_object = Add<HLoadNamedField>( | 1192 HValue* code_object = Add<HLoadNamedField>( |
1161 shared_info, static_cast<HValue*>(NULL), HObjectAccess::ForCodeOffset()); | 1193 shared_info, static_cast<HValue*>(NULL), HObjectAccess::ForCodeOffset()); |
1162 Add<HStoreCodeEntry>(js_function, code_object); | 1194 Add<HStoreCodeEntry>(js_function, code_object); |
1163 } | 1195 } |
1164 | 1196 |
1165 | 1197 |
| 1198 HInstruction* CodeStubGraphBuilderBase::LoadFromOptimizedCodeMap( |
| 1199 HValue* optimized_map, |
| 1200 HValue* iterator, |
| 1201 int field_offset) { |
| 1202 // By making sure to express these loads in the form [<hvalue> + constant] |
| 1203 // the keyed load can be hoisted. |
| 1204 ASSERT(field_offset >= 0 && field_offset < SharedFunctionInfo::kEntryLength); |
| 1205 HValue* field_slot = iterator; |
| 1206 if (field_offset > 0) { |
| 1207 HValue* field_offset_value = Add<HConstant>(field_offset); |
| 1208 field_slot = AddUncasted<HAdd>(iterator, field_offset_value); |
| 1209 } |
| 1210 HInstruction* field_entry = Add<HLoadKeyed>(optimized_map, field_slot, |
| 1211 static_cast<HValue*>(NULL), FAST_ELEMENTS); |
| 1212 return field_entry; |
| 1213 } |
| 1214 |
| 1215 |
1166 void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap( | 1216 void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap( |
1167 HValue* js_function, | 1217 HValue* js_function, |
1168 HValue* shared_info, | 1218 HValue* shared_info, |
1169 HValue* native_context) { | 1219 HValue* native_context) { |
1170 Counters* counters = isolate()->counters(); | 1220 Counters* counters = isolate()->counters(); |
1171 IfBuilder is_optimized(this); | 1221 IfBuilder is_optimized(this); |
1172 HInstruction* optimized_map = Add<HLoadNamedField>( | 1222 HInstruction* optimized_map = Add<HLoadNamedField>( |
1173 shared_info, static_cast<HValue*>(NULL), | 1223 shared_info, static_cast<HValue*>(NULL), |
1174 HObjectAccess::ForOptimizedCodeMap()); | 1224 HObjectAccess::ForOptimizedCodeMap()); |
1175 HValue* null_constant = Add<HConstant>(0); | 1225 HValue* null_constant = Add<HConstant>(0); |
1176 is_optimized.If<HCompareObjectEqAndBranch>(optimized_map, null_constant); | 1226 is_optimized.If<HCompareObjectEqAndBranch>(optimized_map, null_constant); |
1177 is_optimized.Then(); | 1227 is_optimized.Then(); |
1178 { | 1228 { |
1179 BuildInstallCode(js_function, shared_info); | 1229 BuildInstallCode(js_function, shared_info); |
1180 } | 1230 } |
1181 is_optimized.Else(); | 1231 is_optimized.Else(); |
1182 { | 1232 { |
1183 AddIncrementCounter(counters->fast_new_closure_try_optimized()); | 1233 AddIncrementCounter(counters->fast_new_closure_try_optimized()); |
1184 // optimized_map points to fixed array of 3-element entries | 1234 // optimized_map points to fixed array of 3-element entries |
1185 // (native context, optimized code, literals). | 1235 // (native context, optimized code, literals). |
1186 // Map must never be empty, so check the first elements. | 1236 // Map must never be empty, so check the first elements. |
1187 Label install_optimized; | 1237 HValue* first_entry_index = |
1188 HValue* first_context_slot = Add<HLoadNamedField>( | 1238 Add<HConstant>(SharedFunctionInfo::kEntriesStart); |
1189 optimized_map, static_cast<HValue*>(NULL), | |
1190 HObjectAccess::ForFirstContextSlot()); | |
1191 HValue* first_osr_ast_slot = Add<HLoadNamedField>( | |
1192 optimized_map, static_cast<HValue*>(NULL), | |
1193 HObjectAccess::ForFirstOsrAstIdSlot()); | |
1194 HValue* osr_ast_id_none = Add<HConstant>(BailoutId::None().ToInt()); | |
1195 IfBuilder already_in(this); | 1239 IfBuilder already_in(this); |
1196 already_in.If<HCompareObjectEqAndBranch>(native_context, | 1240 BuildCheckAndInstallOptimizedCode(js_function, native_context, &already_in, |
1197 first_context_slot); | 1241 optimized_map, first_entry_index); |
1198 already_in.AndIf<HCompareObjectEqAndBranch>(first_osr_ast_slot, | |
1199 osr_ast_id_none); | |
1200 already_in.Then(); | |
1201 { | |
1202 HValue* code_object = Add<HLoadNamedField>( | |
1203 optimized_map, static_cast<HValue*>(NULL), | |
1204 HObjectAccess::ForFirstCodeSlot()); | |
1205 BuildInstallOptimizedCode(js_function, native_context, code_object); | |
1206 } | |
1207 already_in.Else(); | 1242 already_in.Else(); |
1208 { | 1243 { |
| 1244 // Iterate through the rest of map backwards. Do not double check first |
| 1245 // entry. After the loop, if no matching optimized code was found, |
| 1246 // install unoptimized code. |
| 1247 // for(i = map.length() - SharedFunctionInfo::kEntryLength; |
| 1248 // i > SharedFunctionInfo::kEntriesStart; |
| 1249 // i -= SharedFunctionInfo::kEntryLength) { .. } |
1209 HValue* shared_function_entry_length = | 1250 HValue* shared_function_entry_length = |
1210 Add<HConstant>(SharedFunctionInfo::kEntryLength); | 1251 Add<HConstant>(SharedFunctionInfo::kEntryLength); |
1211 LoopBuilder loop_builder(this, | 1252 LoopBuilder loop_builder(this, |
1212 context(), | 1253 context(), |
1213 LoopBuilder::kPostDecrement, | 1254 LoopBuilder::kPostDecrement, |
1214 shared_function_entry_length); | 1255 shared_function_entry_length); |
1215 HValue* array_length = Add<HLoadNamedField>( | 1256 HValue* array_length = Add<HLoadNamedField>( |
1216 optimized_map, static_cast<HValue*>(NULL), | 1257 optimized_map, static_cast<HValue*>(NULL), |
1217 HObjectAccess::ForFixedArrayLength()); | 1258 HObjectAccess::ForFixedArrayLength()); |
1218 HValue* slot_iterator = loop_builder.BeginBody(array_length, | 1259 HValue* start_pos = AddUncasted<HSub>(array_length, |
1219 graph()->GetConstant0(), | 1260 shared_function_entry_length); |
1220 Token::GT); | 1261 HValue* slot_iterator = loop_builder.BeginBody(start_pos, |
| 1262 first_entry_index, |
| 1263 Token::GT); |
1221 { | 1264 { |
1222 // Iterate through the rest of map backwards. | 1265 IfBuilder done_check(this); |
1223 // Do not double check first entry. | 1266 BuildCheckAndInstallOptimizedCode(js_function, native_context, |
1224 HValue* second_entry_index = | 1267 &done_check, |
1225 Add<HConstant>(SharedFunctionInfo::kSecondEntryIndex); | 1268 optimized_map, |
1226 IfBuilder restore_check(this); | 1269 slot_iterator); |
1227 restore_check.If<HCompareNumericAndBranch>( | 1270 // Fall out of the loop |
1228 slot_iterator, second_entry_index, Token::EQ); | 1271 loop_builder.Break(); |
1229 restore_check.Then(); | |
1230 { | |
1231 // Store the unoptimized code | |
1232 BuildInstallCode(js_function, shared_info); | |
1233 loop_builder.Break(); | |
1234 } | |
1235 restore_check.Else(); | |
1236 { | |
1237 STATIC_ASSERT(SharedFunctionInfo::kContextOffset == 0); | |
1238 STATIC_ASSERT(SharedFunctionInfo::kEntryLength - | |
1239 SharedFunctionInfo::kOsrAstIdOffset == 1); | |
1240 HValue* native_context_slot = AddUncasted<HSub>( | |
1241 slot_iterator, shared_function_entry_length); | |
1242 HValue* osr_ast_id_slot = AddUncasted<HSub>( | |
1243 slot_iterator, graph()->GetConstant1()); | |
1244 HInstruction* native_context_entry = Add<HLoadKeyed>(optimized_map, | |
1245 native_context_slot, static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
1246 HInstruction* osr_ast_id_entry = Add<HLoadKeyed>(optimized_map, | |
1247 osr_ast_id_slot, static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
1248 IfBuilder done_check(this); | |
1249 done_check.If<HCompareObjectEqAndBranch>(native_context, | |
1250 native_context_entry); | |
1251 done_check.AndIf<HCompareObjectEqAndBranch>(osr_ast_id_entry, | |
1252 osr_ast_id_none); | |
1253 done_check.Then(); | |
1254 { | |
1255 // Hit: fetch the optimized code. | |
1256 HValue* code_slot = AddUncasted<HAdd>( | |
1257 native_context_slot, graph()->GetConstant1()); | |
1258 HValue* code_object = Add<HLoadKeyed>(optimized_map, | |
1259 code_slot, static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
1260 BuildInstallOptimizedCode(js_function, native_context, code_object); | |
1261 | |
1262 // Fall out of the loop | |
1263 loop_builder.Break(); | |
1264 } | |
1265 done_check.Else(); | |
1266 done_check.End(); | |
1267 } | |
1268 restore_check.End(); | |
1269 } | 1272 } |
1270 loop_builder.EndBody(); | 1273 loop_builder.EndBody(); |
| 1274 |
| 1275 // If slot_iterator equals first entry index, then we failed to find and |
| 1276 // install optimized code |
| 1277 IfBuilder no_optimized_code_check(this); |
| 1278 no_optimized_code_check.If<HCompareNumericAndBranch>( |
| 1279 slot_iterator, first_entry_index, Token::EQ); |
| 1280 no_optimized_code_check.Then(); |
| 1281 { |
| 1282 // Store the unoptimized code |
| 1283 BuildInstallCode(js_function, shared_info); |
| 1284 } |
1271 } | 1285 } |
1272 already_in.End(); | |
1273 } | 1286 } |
1274 is_optimized.End(); | |
1275 } | 1287 } |
1276 | 1288 |
1277 | 1289 |
1278 template<> | 1290 template<> |
1279 HValue* CodeStubGraphBuilder<FastNewClosureStub>::BuildCodeStub() { | 1291 HValue* CodeStubGraphBuilder<FastNewClosureStub>::BuildCodeStub() { |
1280 Counters* counters = isolate()->counters(); | 1292 Counters* counters = isolate()->counters(); |
1281 Factory* factory = isolate()->factory(); | 1293 Factory* factory = isolate()->factory(); |
1282 HInstruction* empty_fixed_array = | 1294 HInstruction* empty_fixed_array = |
1283 Add<HConstant>(factory->empty_fixed_array()); | 1295 Add<HConstant>(factory->empty_fixed_array()); |
1284 HValue* shared_info = GetParameter(0); | 1296 HValue* shared_info = GetParameter(0); |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1415 return BuildRegExpConstructResult(length, index, input); | 1427 return BuildRegExpConstructResult(length, index, input); |
1416 } | 1428 } |
1417 | 1429 |
1418 | 1430 |
1419 Handle<Code> RegExpConstructResultStub::GenerateCode(Isolate* isolate) { | 1431 Handle<Code> RegExpConstructResultStub::GenerateCode(Isolate* isolate) { |
1420 return DoGenerateCode(isolate, this); | 1432 return DoGenerateCode(isolate, this); |
1421 } | 1433 } |
1422 | 1434 |
1423 | 1435 |
1424 } } // namespace v8::internal | 1436 } } // namespace v8::internal |
OLD | NEW |