OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/code-factory.h" | 5 #include "src/code-factory.h" |
6 #include "src/compiler/access-builder.h" | 6 #include "src/compiler/access-builder.h" |
7 #include "src/compiler/js-graph.h" | 7 #include "src/compiler/js-graph.h" |
8 #include "src/compiler/js-typed-lowering.h" | 8 #include "src/compiler/js-typed-lowering.h" |
9 #include "src/compiler/linkage.h" | 9 #include "src/compiler/linkage.h" |
10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
(...skipping 1238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1249 return Changed(node); | 1249 return Changed(node); |
1250 } | 1250 } |
1251 | 1251 |
1252 return NoChange(); | 1252 return NoChange(); |
1253 } | 1253 } |
1254 | 1254 |
1255 | 1255 |
1256 Reduction JSTypedLowering::ReduceJSCreateFunctionContext(Node* node) { | 1256 Reduction JSTypedLowering::ReduceJSCreateFunctionContext(Node* node) { |
1257 DCHECK_EQ(IrOpcode::kJSCreateFunctionContext, node->opcode()); | 1257 DCHECK_EQ(IrOpcode::kJSCreateFunctionContext, node->opcode()); |
1258 int slot_count = OpParameter<int>(node->op()); | 1258 int slot_count = OpParameter<int>(node->op()); |
| 1259 Node* const closure = NodeProperties::GetValueInput(node, 0); |
| 1260 |
| 1261 // The closure can be NumberConstant(0) if the closure is global code |
| 1262 // (rather than a function). We exclude that case here. |
| 1263 // TODO(jarin) Find a better way to check that the closure is a function. |
1259 | 1264 |
1260 // Use inline allocation for function contexts up to a size limit. | 1265 // Use inline allocation for function contexts up to a size limit. |
1261 if (FLAG_turbo_allocate && slot_count < kFunctionContextAllocationLimit) { | 1266 if (slot_count < kFunctionContextAllocationLimit && |
| 1267 closure->opcode() != IrOpcode::kNumberConstant) { |
1262 // JSCreateFunctionContext[slot_count < limit]](fun) | 1268 // JSCreateFunctionContext[slot_count < limit]](fun) |
1263 Node* const effect = NodeProperties::GetEffectInput(node); | 1269 Node* const effect = NodeProperties::GetEffectInput(node); |
1264 Node* const control = NodeProperties::GetControlInput(node); | 1270 Node* const control = NodeProperties::GetControlInput(node); |
1265 Node* const closure = NodeProperties::GetValueInput(node, 0); | |
1266 Node* const context = NodeProperties::GetContextInput(node); | 1271 Node* const context = NodeProperties::GetContextInput(node); |
1267 Node* const extension = jsgraph()->ZeroConstant(); | 1272 Node* const extension = jsgraph()->ZeroConstant(); |
1268 Node* const load = graph()->NewNode( | 1273 Node* const load = graph()->NewNode( |
1269 simplified()->LoadField( | 1274 simplified()->LoadField( |
1270 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), | 1275 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), |
1271 context, effect, control); | 1276 context, effect, control); |
1272 AllocationBuilder a(jsgraph(), simplified(), effect, control); | 1277 AllocationBuilder a(jsgraph(), simplified(), effect, control); |
1273 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. | 1278 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. |
1274 int context_length = slot_count + Context::MIN_CONTEXT_SLOTS; | 1279 int context_length = slot_count + Context::MIN_CONTEXT_SLOTS; |
1275 a.AllocateArray(context_length, factory()->function_context_map()); | 1280 a.AllocateArray(context_length, factory()->function_context_map()); |
1276 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); | 1281 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); |
1277 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); | 1282 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); |
1278 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension); | 1283 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension); |
1279 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load); | 1284 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load); |
1280 for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) { | 1285 for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) { |
1281 a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->TheHoleConstant()); | 1286 a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->UndefinedConstant()); |
1282 } | 1287 } |
1283 RelaxControls(node); | 1288 RelaxControls(node); |
1284 a.Finish(node); | 1289 a.Finish(node); |
1285 return Changed(node); | 1290 return Changed(node); |
1286 } | 1291 } |
1287 | 1292 |
1288 // Use the FastNewContextStub only for function contexts up maximum size. | 1293 // Use the FastNewContextStub only for function contexts up maximum size. |
1289 if (slot_count <= FastNewContextStub::kMaximumSlots) { | 1294 if (slot_count <= FastNewContextStub::kMaximumSlots) { |
1290 Isolate* isolate = jsgraph()->isolate(); | 1295 Isolate* isolate = jsgraph()->isolate(); |
1291 Callable callable = CodeFactory::FastNewContext(isolate, slot_count); | 1296 Callable callable = CodeFactory::FastNewContext(isolate, slot_count); |
1292 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | 1297 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
1293 isolate, graph()->zone(), callable.descriptor(), 0, | 1298 isolate, graph()->zone(), callable.descriptor(), 0, |
1294 CallDescriptor::kNoFlags); | 1299 CallDescriptor::kNoFlags); |
1295 const Operator* new_op = common()->Call(desc); | 1300 const Operator* new_op = common()->Call(desc); |
1296 Node* stub_code = jsgraph()->HeapConstant(callable.code()); | 1301 Node* stub_code = jsgraph()->HeapConstant(callable.code()); |
1297 node->InsertInput(graph()->zone(), 0, stub_code); | 1302 node->InsertInput(graph()->zone(), 0, stub_code); |
1298 NodeProperties::ChangeOp(node, new_op); | 1303 NodeProperties::ChangeOp(node, new_op); |
1299 return Changed(node); | 1304 return Changed(node); |
1300 } | 1305 } |
1301 | 1306 |
1302 return NoChange(); | 1307 return NoChange(); |
1303 } | 1308 } |
1304 | 1309 |
1305 | 1310 |
1306 Reduction JSTypedLowering::ReduceJSCreateWithContext(Node* node) { | 1311 Reduction JSTypedLowering::ReduceJSCreateWithContext(Node* node) { |
1307 DCHECK_EQ(IrOpcode::kJSCreateWithContext, node->opcode()); | 1312 DCHECK_EQ(IrOpcode::kJSCreateWithContext, node->opcode()); |
1308 Node* const input = NodeProperties::GetValueInput(node, 0); | 1313 Node* const input = NodeProperties::GetValueInput(node, 0); |
| 1314 Node* const closure = NodeProperties::GetValueInput(node, 1); |
1309 Type* input_type = NodeProperties::GetType(input); | 1315 Type* input_type = NodeProperties::GetType(input); |
1310 | 1316 |
| 1317 // The closure can be NumberConstant(0) if the closure is global code |
| 1318 // (rather than a function). We exclude that case here. |
| 1319 // TODO(jarin) Find a better way to check that the closure is a function. |
| 1320 |
1311 // Use inline allocation for with contexts for regular objects. | 1321 // Use inline allocation for with contexts for regular objects. |
1312 if (FLAG_turbo_allocate && input_type->Is(Type::Receiver())) { | 1322 if (input_type->Is(Type::Receiver()) && |
| 1323 closure->opcode() != IrOpcode::kNumberConstant) { |
1313 // JSCreateWithContext(o:receiver, fun) | 1324 // JSCreateWithContext(o:receiver, fun) |
1314 Node* const effect = NodeProperties::GetEffectInput(node); | 1325 Node* const effect = NodeProperties::GetEffectInput(node); |
1315 Node* const control = NodeProperties::GetControlInput(node); | 1326 Node* const control = NodeProperties::GetControlInput(node); |
1316 Node* const closure = NodeProperties::GetValueInput(node, 1); | |
1317 Node* const context = NodeProperties::GetContextInput(node); | 1327 Node* const context = NodeProperties::GetContextInput(node); |
1318 Node* const load = graph()->NewNode( | 1328 Node* const load = graph()->NewNode( |
1319 simplified()->LoadField( | 1329 simplified()->LoadField( |
1320 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), | 1330 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), |
1321 context, effect, control); | 1331 context, effect, control); |
1322 AllocationBuilder a(jsgraph(), simplified(), effect, control); | 1332 AllocationBuilder a(jsgraph(), simplified(), effect, control); |
1323 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. | 1333 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. |
1324 a.AllocateArray(Context::MIN_CONTEXT_SLOTS, factory()->with_context_map()); | 1334 a.AllocateArray(Context::MIN_CONTEXT_SLOTS, factory()->with_context_map()); |
1325 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); | 1335 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); |
1326 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); | 1336 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); |
1327 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), input); | 1337 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), input); |
1328 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load); | 1338 a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load); |
1329 RelaxControls(node); | 1339 RelaxControls(node); |
1330 a.Finish(node); | 1340 a.Finish(node); |
1331 return Changed(node); | 1341 return Changed(node); |
1332 } | 1342 } |
1333 | 1343 |
1334 return NoChange(); | 1344 return NoChange(); |
1335 } | 1345 } |
1336 | 1346 |
1337 | 1347 |
1338 Reduction JSTypedLowering::ReduceJSCreateBlockContext(Node* node) { | 1348 Reduction JSTypedLowering::ReduceJSCreateBlockContext(Node* node) { |
1339 DCHECK_EQ(IrOpcode::kJSCreateBlockContext, node->opcode()); | 1349 DCHECK_EQ(IrOpcode::kJSCreateBlockContext, node->opcode()); |
1340 Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node); | 1350 Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node); |
1341 int context_length = scope_info->ContextLength(); | 1351 int context_length = scope_info->ContextLength(); |
| 1352 Node* const closure = NodeProperties::GetValueInput(node, 0); |
| 1353 |
| 1354 // The closure can be NumberConstant(0) if the closure is global code |
| 1355 // (rather than a function). We exclude that case here. |
| 1356 // TODO(jarin) Find a better way to check that the closure is a function. |
1342 | 1357 |
1343 // Use inline allocation for block contexts up to a size limit. | 1358 // Use inline allocation for block contexts up to a size limit. |
1344 if (FLAG_turbo_allocate && context_length < kBlockContextAllocationLimit) { | 1359 if (context_length < kBlockContextAllocationLimit && |
| 1360 closure->opcode() != IrOpcode::kNumberConstant) { |
1345 // JSCreateBlockContext[scope[length < limit]](fun) | 1361 // JSCreateBlockContext[scope[length < limit]](fun) |
1346 Node* const effect = NodeProperties::GetEffectInput(node); | 1362 Node* const effect = NodeProperties::GetEffectInput(node); |
1347 Node* const control = NodeProperties::GetControlInput(node); | 1363 Node* const control = NodeProperties::GetControlInput(node); |
1348 Node* const closure = NodeProperties::GetValueInput(node, 1); | |
1349 Node* const context = NodeProperties::GetContextInput(node); | 1364 Node* const context = NodeProperties::GetContextInput(node); |
1350 Node* const extension = jsgraph()->Constant(scope_info); | 1365 Node* const extension = jsgraph()->Constant(scope_info); |
1351 Node* const load = graph()->NewNode( | 1366 Node* const load = graph()->NewNode( |
1352 simplified()->LoadField( | 1367 simplified()->LoadField( |
1353 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), | 1368 AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), |
1354 context, effect, control); | 1369 context, effect, control); |
1355 AllocationBuilder a(jsgraph(), simplified(), effect, control); | 1370 AllocationBuilder a(jsgraph(), simplified(), effect, control); |
1356 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. | 1371 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. |
1357 a.AllocateArray(context_length, factory()->block_context_map()); | 1372 a.AllocateArray(context_length, factory()->block_context_map()); |
1358 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); | 1373 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); |
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1821 } | 1836 } |
1822 | 1837 |
1823 | 1838 |
1824 MachineOperatorBuilder* JSTypedLowering::machine() const { | 1839 MachineOperatorBuilder* JSTypedLowering::machine() const { |
1825 return jsgraph()->machine(); | 1840 return jsgraph()->machine(); |
1826 } | 1841 } |
1827 | 1842 |
1828 } // namespace compiler | 1843 } // namespace compiler |
1829 } // namespace internal | 1844 } // namespace internal |
1830 } // namespace v8 | 1845 } // namespace v8 |
OLD | NEW |