| 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 |