OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/compiler/js-create-lowering.h" | 5 #include "src/compiler/js-create-lowering.h" |
6 | 6 |
7 #include "src/allocation-site-scopes.h" | 7 #include "src/allocation-site-scopes.h" |
8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
9 #include "src/compilation-dependencies.h" | 9 #include "src/compilation-dependencies.h" |
10 #include "src/compiler/access-builder.h" | 10 #include "src/compiler/access-builder.h" |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 | 101 |
102 // Retrieves the frame state holding actual argument values. | 102 // Retrieves the frame state holding actual argument values. |
103 Node* GetArgumentsFrameState(Node* frame_state) { | 103 Node* GetArgumentsFrameState(Node* frame_state) { |
104 Node* const outer_state = NodeProperties::GetFrameStateInput(frame_state, 0); | 104 Node* const outer_state = NodeProperties::GetFrameStateInput(frame_state, 0); |
105 FrameStateInfo outer_state_info = OpParameter<FrameStateInfo>(outer_state); | 105 FrameStateInfo outer_state_info = OpParameter<FrameStateInfo>(outer_state); |
106 return outer_state_info.type() == FrameStateType::kArgumentsAdaptor | 106 return outer_state_info.type() == FrameStateType::kArgumentsAdaptor |
107 ? outer_state | 107 ? outer_state |
108 : frame_state; | 108 : frame_state; |
109 } | 109 } |
110 | 110 |
111 // Maximum instance size for which allocations will be inlined. | 111 // Checks whether allocation using the given target and new.target can be |
112 const int kMaxInlineInstanceSize = 64 * kPointerSize; | 112 // inlined. |
113 | 113 bool IsAllocationInlineable(Handle<JSFunction> target, |
114 // Checks whether allocation using the given constructor can be inlined. | 114 Handle<JSFunction> new_target) { |
115 bool IsAllocationInlineable(Handle<JSFunction> constructor) { | 115 return new_target->has_initial_map() && |
116 // TODO(bmeurer): Further relax restrictions on inlining, i.e. | 116 new_target->initial_map()->constructor_or_backpointer() == *target; |
117 // instance type and maybe instance size (inobject properties | |
118 // are limited anyways by the runtime). | |
119 return constructor->has_initial_map() && | |
120 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && | |
121 constructor->initial_map()->instance_size() < kMaxInlineInstanceSize; | |
122 } | 117 } |
123 | 118 |
124 // When initializing arrays, we'll unfold the loop if the number of | 119 // When initializing arrays, we'll unfold the loop if the number of |
125 // elements is known to be of this type. | 120 // elements is known to be of this type. |
126 const int kElementLoopUnrollLimit = 16; | 121 const int kElementLoopUnrollLimit = 16; |
127 | 122 |
128 // Limits up to which context allocations are inlined. | 123 // Limits up to which context allocations are inlined. |
129 const int kFunctionContextAllocationLimit = 16; | 124 const int kFunctionContextAllocationLimit = 16; |
130 const int kBlockContextAllocationLimit = 16; | 125 const int kBlockContextAllocationLimit = 16; |
131 | 126 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
223 break; | 218 break; |
224 } | 219 } |
225 return NoChange(); | 220 return NoChange(); |
226 } | 221 } |
227 | 222 |
228 Reduction JSCreateLowering::ReduceJSCreate(Node* node) { | 223 Reduction JSCreateLowering::ReduceJSCreate(Node* node) { |
229 DCHECK_EQ(IrOpcode::kJSCreate, node->opcode()); | 224 DCHECK_EQ(IrOpcode::kJSCreate, node->opcode()); |
230 Node* const target = NodeProperties::GetValueInput(node, 0); | 225 Node* const target = NodeProperties::GetValueInput(node, 0); |
231 Type* const target_type = NodeProperties::GetType(target); | 226 Type* const target_type = NodeProperties::GetType(target); |
232 Node* const new_target = NodeProperties::GetValueInput(node, 1); | 227 Node* const new_target = NodeProperties::GetValueInput(node, 1); |
| 228 Type* const new_target_type = NodeProperties::GetType(new_target); |
233 Node* const effect = NodeProperties::GetEffectInput(node); | 229 Node* const effect = NodeProperties::GetEffectInput(node); |
234 // TODO(turbofan): Add support for NewTarget passed to JSCreate. | 230 // Extract constructor and original constructor function. |
235 if (target != new_target) return NoChange(); | |
236 // Extract constructor function. | |
237 if (target_type->IsConstant() && | 231 if (target_type->IsConstant() && |
238 target_type->AsConstant()->Value()->IsJSFunction()) { | 232 new_target_type->IsConstant() && |
| 233 new_target_type->AsConstant()->Value()->IsJSFunction()) { |
239 Handle<JSFunction> constructor = | 234 Handle<JSFunction> constructor = |
240 Handle<JSFunction>::cast(target_type->AsConstant()->Value()); | 235 Handle<JSFunction>::cast(target_type->AsConstant()->Value()); |
| 236 Handle<JSFunction> original_constructor = |
| 237 Handle<JSFunction>::cast(new_target_type->AsConstant()->Value()); |
241 DCHECK(constructor->IsConstructor()); | 238 DCHECK(constructor->IsConstructor()); |
242 // Force completion of inobject slack tracking before | 239 DCHECK(original_constructor->IsConstructor()); |
243 // generating code to finalize the instance size. | |
244 constructor->CompleteInobjectSlackTrackingIfActive(); | |
245 | 240 |
246 // Check if we can inline the allocation. | 241 // Check if we can inline the allocation. |
247 if (IsAllocationInlineable(constructor)) { | 242 if (IsAllocationInlineable(constructor, original_constructor)) { |
248 // Compute instance size from initial map of {constructor}. | 243 // Force completion of inobject slack tracking before |
249 Handle<Map> initial_map(constructor->initial_map(), isolate()); | 244 // generating code to finalize the instance size. |
| 245 original_constructor->CompleteInobjectSlackTrackingIfActive(); |
| 246 |
| 247 // Compute instance size from initial map of {original_constructor}. |
| 248 Handle<Map> initial_map(original_constructor->initial_map(), isolate()); |
250 int const instance_size = initial_map->instance_size(); | 249 int const instance_size = initial_map->instance_size(); |
251 | 250 |
252 // Add a dependency on the {initial_map} to make sure that this code is | 251 // Add a dependency on the {initial_map} to make sure that this code is |
253 // deoptimized whenever the {initial_map} of the {constructor} changes. | 252 // deoptimized whenever the {initial_map} of the {original_constructor} |
| 253 // changes. |
254 dependencies()->AssumeInitialMapCantChange(initial_map); | 254 dependencies()->AssumeInitialMapCantChange(initial_map); |
255 | 255 |
256 // Emit code to allocate the JSObject instance for the {constructor}. | 256 // Emit code to allocate the JSObject instance for the |
| 257 // {original_constructor}. |
257 AllocationBuilder a(jsgraph(), effect, graph()->start()); | 258 AllocationBuilder a(jsgraph(), effect, graph()->start()); |
258 a.Allocate(instance_size); | 259 a.Allocate(instance_size); |
259 a.Store(AccessBuilder::ForMap(), initial_map); | 260 a.Store(AccessBuilder::ForMap(), initial_map); |
260 a.Store(AccessBuilder::ForJSObjectProperties(), | 261 a.Store(AccessBuilder::ForJSObjectProperties(), |
261 jsgraph()->EmptyFixedArrayConstant()); | 262 jsgraph()->EmptyFixedArrayConstant()); |
262 a.Store(AccessBuilder::ForJSObjectElements(), | 263 a.Store(AccessBuilder::ForJSObjectElements(), |
263 jsgraph()->EmptyFixedArrayConstant()); | 264 jsgraph()->EmptyFixedArrayConstant()); |
264 for (int i = 0; i < initial_map->GetInObjectProperties(); ++i) { | 265 for (int i = 0; i < initial_map->GetInObjectProperties(); ++i) { |
265 a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i), | 266 a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i), |
266 jsgraph()->UndefinedConstant()); | 267 jsgraph()->UndefinedConstant()); |
(...skipping 819 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1086 return jsgraph()->simplified(); | 1087 return jsgraph()->simplified(); |
1087 } | 1088 } |
1088 | 1089 |
1089 MachineOperatorBuilder* JSCreateLowering::machine() const { | 1090 MachineOperatorBuilder* JSCreateLowering::machine() const { |
1090 return jsgraph()->machine(); | 1091 return jsgraph()->machine(); |
1091 } | 1092 } |
1092 | 1093 |
1093 } // namespace compiler | 1094 } // namespace compiler |
1094 } // namespace internal | 1095 } // namespace internal |
1095 } // namespace v8 | 1096 } // namespace v8 |
OLD | NEW |