Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(121)

Unified Diff: src/compiler/js-typed-lowering.cc

Issue 1465203002: [turbofan] Initial support for inline allocations of arrays. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix unbounded inlining. Reduce code duplication. Add proper code dependencies. Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/js-typed-lowering.h ('k') | src/type-cache.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/js-typed-lowering.cc
diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc
index 79e40aa3b667267ae1efa76399b2a9fa96550165..9c684b31cceed4308f2efc5e46448eaae74c7d27 100644
--- a/src/compiler/js-typed-lowering.cc
+++ b/src/compiler/js-typed-lowering.cc
@@ -12,31 +12,14 @@
#include "src/compiler/node-properties.h"
#include "src/compiler/operator-properties.h"
#include "src/compiler/state-values-utils.h"
+#include "src/type-cache.h"
#include "src/types.h"
namespace v8 {
namespace internal {
namespace compiler {
-// TODO(turbofan): js-typed-lowering improvements possible
-// - immediately put in type bounds for all new nodes
-// - relax effects from generic but not-side-effecting operations
-
-
-JSTypedLowering::JSTypedLowering(Editor* editor,
- CompilationDependencies* dependencies,
- Flags flags, JSGraph* jsgraph, Zone* zone)
- : AdvancedReducer(editor),
- dependencies_(dependencies),
- flags_(flags),
- jsgraph_(jsgraph) {
- for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) {
- double min = kMinInt / (1 << k);
- double max = kMaxInt / (1 << k);
- shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone());
- }
-}
-
+namespace {
// A helper class to construct inline allocations on the simplified operator
// level. This keeps track of the effect chain for initial stores on a newly
@@ -50,10 +33,11 @@ class AllocationBuilder final {
control_(control) {}
// Primitive allocation of static size.
- void Allocate(int size) {
+ void Allocate(int size, PretenureFlag pretenure = NOT_TENURED) {
effect_ = graph()->NewNode(common()->BeginRegion(), effect_);
- allocation_ = graph()->NewNode(
- simplified()->Allocate(), jsgraph()->Constant(size), effect_, control_);
+ allocation_ =
+ graph()->NewNode(simplified()->Allocate(pretenure),
+ jsgraph()->Constant(size), effect_, control_);
effect_ = allocation_;
}
@@ -63,9 +47,21 @@ class AllocationBuilder final {
value, effect_, control_);
}
+ // Primitive store into an element.
+ void Store(ElementAccess const& access, Node* index, Node* value) {
+ effect_ = graph()->NewNode(simplified()->StoreElement(access), allocation_,
+ index, value, effect_, control_);
+ }
+
// Compound allocation of a FixedArray.
- void AllocateArray(int length, Handle<Map> map) {
- Allocate(FixedArray::SizeFor(length));
+ void AllocateArray(int length, Handle<Map> map,
+ PretenureFlag pretenure = NOT_TENURED) {
+ DCHECK(map->instance_type() == FIXED_ARRAY_TYPE ||
+ map->instance_type() == FIXED_DOUBLE_ARRAY_TYPE);
+ int size = (map->instance_type() == FIXED_ARRAY_TYPE)
+ ? FixedArray::SizeFor(length)
+ : FixedDoubleArray::SizeFor(length);
+ Allocate(size, pretenure);
Store(AccessBuilder::ForMap(), map);
Store(AccessBuilder::ForFixedArrayLength(), jsgraph()->Constant(length));
}
@@ -100,6 +96,8 @@ class AllocationBuilder final {
Node* control_;
};
+} // namespace
+
// A helper class to simplify the process of reducing a single binop node with a
// JSOperator. This class manages the rewriting of context, control, and effect
@@ -417,6 +415,27 @@ class JSBinopReduction final {
};
+// TODO(turbofan): js-typed-lowering improvements possible
+// - immediately put in type bounds for all new nodes
+// - relax effects from generic but not-side-effecting operations
+
+
+JSTypedLowering::JSTypedLowering(Editor* editor,
+ CompilationDependencies* dependencies,
+ Flags flags, JSGraph* jsgraph, Zone* zone)
+ : AdvancedReducer(editor),
+ dependencies_(dependencies),
+ flags_(flags),
+ jsgraph_(jsgraph),
+ type_cache_(TypeCache::Get()) {
+ for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) {
+ double min = kMinInt / (1 << k);
+ double max = kMaxInt / (1 << k);
+ shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone());
+ }
+}
+
+
Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
JSBinopReduction r(this, node);
if (r.BothInputsAre(Type::Number())) {
@@ -1561,11 +1580,81 @@ Reduction JSTypedLowering::ReduceJSCreateArguments(Node* node) {
}
+Reduction JSTypedLowering::ReduceNewArray(Node* node, Node* length,
+ int capacity,
+ Handle<AllocationSite> site) {
+ DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
+ Node* target = NodeProperties::GetValueInput(node, 0);
+ Type* target_type = NodeProperties::GetType(target);
+ Node* context = NodeProperties::GetContextInput(node);
+ Node* effect = NodeProperties::GetEffectInput(node);
+ Node* control = NodeProperties::GetControlInput(node);
+
+ // Extract transition and tenuring feedback from the {site} and add
+ // appropriate code dependencies on the {site} if deoptimization is
+ // enabled.
+ PretenureFlag pretenure = site->GetPretenureMode();
+ ElementsKind elements_kind = site->GetElementsKind();
+ if (flags() & kDeoptimizationEnabled) {
+ dependencies()->AssumeTenuringDecision(site);
+ dependencies()->AssumeTransitionStable(site);
+ }
+
+ // Retrieve the initial map for the array from the appropriate native context.
+ Node* js_array_map;
+ if (target_type->IsConstant()) {
+ Handle<JSFunction> target_function =
+ Handle<JSFunction>::cast(target_type->AsConstant()->Value());
+ Handle<FixedArray> js_array_maps(
+ FixedArray::cast(target_function->native_context()->js_array_maps()),
+ isolate());
+ js_array_map = jsgraph()->Constant(
+ handle(js_array_maps->get(elements_kind), isolate()));
+ } else {
+ Node* global_object = effect = graph()->NewNode(
+ javascript()->LoadContext(0, Context::GLOBAL_OBJECT_INDEX, true),
+ context, context, effect);
+ Node* native_context = effect =
+ graph()->NewNode(simplified()->LoadField(
+ AccessBuilder::ForJSGlobalObjectNativeContext()),
+ global_object, effect, control);
+ Node* js_array_maps = effect = graph()->NewNode(
+ javascript()->LoadContext(0, Context::JS_ARRAY_MAPS_INDEX, true),
+ native_context, native_context, effect);
+ js_array_map = effect =
+ graph()->NewNode(simplified()->LoadField(
+ AccessBuilder::ForFixedArraySlot(elements_kind)),
+ js_array_maps, effect, control);
+ }
+
+ // Setup elements and properties.
+ Node* elements;
+ if (capacity == 0) {
+ elements = jsgraph()->EmptyFixedArrayConstant();
+ } else {
+ elements = effect =
+ AllocateElements(effect, control, elements_kind, capacity, pretenure);
+ }
+ Node* properties = jsgraph()->EmptyFixedArrayConstant();
+
+ // Perform the allocation of the actual JSArray object.
+ AllocationBuilder a(jsgraph(), effect, control);
+ a.Allocate(JSArray::kSize, pretenure);
+ a.Store(AccessBuilder::ForMap(), js_array_map);
+ a.Store(AccessBuilder::ForJSObjectProperties(), properties);
+ a.Store(AccessBuilder::ForJSObjectElements(), elements);
+ a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length);
+ RelaxControls(node);
+ a.FinishAndChange(node);
+ return Changed(node);
+}
+
+
Reduction JSTypedLowering::ReduceJSCreateArray(Node* node) {
DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
CreateArrayParameters const& p = CreateArrayParametersOf(node->op());
- Node* const target = NodeProperties::GetValueInput(node, 0);
- Node* const new_target = NodeProperties::GetValueInput(node, 1);
+ Node* target = NodeProperties::GetValueInput(node, 0);
+ Node* new_target = NodeProperties::GetValueInput(node, 1);
// TODO(bmeurer): Optimize the subclassing case.
if (target != new_target) return NoChange();
@@ -1573,16 +1662,34 @@ Reduction JSTypedLowering::ReduceJSCreateArray(Node* node) {
// Check if we have a feedback {site} on the {node}.
Handle<AllocationSite> site = p.site();
if (p.site().is_null()) return NoChange();
- ElementsKind const elements_kind = site->GetElementsKind();
- AllocationSiteOverrideMode override_mode =
- (AllocationSite::GetMode(elements_kind) == TRACK_ALLOCATION_SITE)
- ? DISABLE_ALLOCATION_SITES
- : DONT_OVERRIDE;
+
+ // Attempt to inline calls to the Array constructor for the relevant cases
+ // where either no arguments are provided, or exactly one unsigned number
+ // argument is given.
+ if (site->CanInlineCall()) {
+ if (p.arity() == 0) {
+ Node* length = jsgraph()->ZeroConstant();
+ int capacity = JSArray::kPreallocatedArrayElements;
+ return ReduceNewArray(node, length, capacity, site);
+ } else if (p.arity() == 1) {
+ Node* length = NodeProperties::GetValueInput(node, 2);
+ Type* length_type = NodeProperties::GetType(length);
+ if (length_type->Is(type_cache_.kElementLoopUnrollType)) {
+ int capacity = static_cast<int>(length_type->Max());
+ return ReduceNewArray(node, length, capacity, site);
+ }
+ }
+ }
// Reduce {node} to the appropriate ArrayConstructorStub backend.
// Note that these stubs "behave" like JSFunctions, which means they
// expect a receiver on the stack, which they remove. We just push
// undefined for the receiver.
+ ElementsKind elements_kind = site->GetElementsKind();
+ AllocationSiteOverrideMode override_mode =
+ (AllocationSite::GetMode(elements_kind) == TRACK_ALLOCATION_SITE)
+ ? DISABLE_ALLOCATION_SITES
+ : DONT_OVERRIDE;
if (p.arity() == 0) {
ArrayNoArgumentConstructorStub stub(isolate(), elements_kind,
override_mode);
@@ -1590,7 +1697,7 @@ Reduction JSTypedLowering::ReduceJSCreateArray(Node* node) {
isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), 1,
CallDescriptor::kNeedsFrameState);
node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode()));
- node->InsertInput(graph()->zone(), 2, jsgraph()->UndefinedConstant());
+ node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site));
node->InsertInput(graph()->zone(), 3, jsgraph()->UndefinedConstant());
NodeProperties::ChangeOp(node, common()->Call(desc));
return Changed(node);
@@ -1615,7 +1722,7 @@ Reduction JSTypedLowering::ReduceJSCreateArray(Node* node) {
isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(),
arity + 1, CallDescriptor::kNeedsFrameState);
node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode()));
- node->InsertInput(graph()->zone(), 2, jsgraph()->UndefinedConstant());
+ node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site));
node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(arity));
node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
NodeProperties::ChangeOp(node, common()->Call(desc));
@@ -2441,6 +2548,34 @@ Node* JSTypedLowering::AllocateAliasedArguments(
}
+Node* JSTypedLowering::AllocateElements(Node* effect, Node* control,
+ ElementsKind elements_kind,
+ int capacity, PretenureFlag pretenure) {
+ DCHECK_LE(1, capacity);
+ DCHECK_LE(capacity, JSArray::kInitialMaxFastElementArray);
+
+ Handle<Map> elements_map = IsFastDoubleElementsKind(elements_kind)
+ ? factory()->fixed_double_array_map()
+ : factory()->fixed_array_map();
+ ElementAccess access = IsFastDoubleElementsKind(elements_kind)
+ ? AccessBuilder::ForFixedDoubleArrayElement()
+ : AccessBuilder::ForFixedArrayElement();
+ Node* value =
+ IsFastDoubleElementsKind(elements_kind)
+ ? jsgraph()->Float64Constant(bit_cast<double>(kHoleNanInt64))
+ : jsgraph()->TheHoleConstant();
+
+ // Actually allocate the backing store.
+ AllocationBuilder a(jsgraph(), effect, control);
+ a.AllocateArray(capacity, elements_map, pretenure);
+ for (int i = 0; i < capacity; ++i) {
+ Node* index = jsgraph()->Int32Constant(i);
+ a.Store(access, index, value);
+ }
+ return a.Finish();
+}
+
+
Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); }
« no previous file with comments | « src/compiler/js-typed-lowering.h ('k') | src/type-cache.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698