Commit f695855c authored by Jaroslav Sevcik's avatar Jaroslav Sevcik Committed by Commit Bot

[turbofan] Brokerize JSCreateLowering::ReduceJSCreate

Bug: v8:7790
Change-Id: I918af0461e86ce8eacb9155de18954d8b6270ecc
Reviewed-on: https://chromium-review.googlesource.com/1123831
Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54317}
parent d78235e3
...@@ -41,11 +41,14 @@ Node* GetArgumentsFrameState(Node* frame_state) { ...@@ -41,11 +41,14 @@ Node* GetArgumentsFrameState(Node* frame_state) {
// Checks whether allocation using the given target and new.target can be // Checks whether allocation using the given target and new.target can be
// inlined. // inlined.
bool IsAllocationInlineable(Handle<JSFunction> target, bool IsAllocationInlineable(const JSFunctionRef& target,
Handle<JSFunction> new_target) { const JSFunctionRef& new_target,
return new_target->has_initial_map() && const JSHeapBroker* broker) {
!new_target->initial_map()->is_dictionary_map() && return new_target.has_initial_map() &&
new_target->initial_map()->constructor_or_backpointer() == *target; !new_target.initial_map(broker).is_dictionary_map() &&
new_target.initial_map(broker)
.constructor_or_backpointer(broker)
.equals(target);
} }
// When initializing arrays, we'll unfold the loop if the number of // When initializing arrays, we'll unfold the loop if the number of
...@@ -110,6 +113,7 @@ Reduction JSCreateLowering::Reduce(Node* node) { ...@@ -110,6 +113,7 @@ Reduction JSCreateLowering::Reduce(Node* node) {
} }
Reduction JSCreateLowering::ReduceJSCreate(Node* node) { Reduction JSCreateLowering::ReduceJSCreate(Node* node) {
DisallowHandleDereference disallow_handle_dereference;
DCHECK_EQ(IrOpcode::kJSCreate, node->opcode()); DCHECK_EQ(IrOpcode::kJSCreate, node->opcode());
Node* const target = NodeProperties::GetValueInput(node, 0); Node* const target = NodeProperties::GetValueInput(node, 0);
Type const target_type = NodeProperties::GetType(target); Type const target_type = NodeProperties::GetType(target);
...@@ -118,48 +122,52 @@ Reduction JSCreateLowering::ReduceJSCreate(Node* node) { ...@@ -118,48 +122,52 @@ Reduction JSCreateLowering::ReduceJSCreate(Node* node) {
Node* const effect = NodeProperties::GetEffectInput(node); Node* const effect = NodeProperties::GetEffectInput(node);
Node* const control = NodeProperties::GetControlInput(node); Node* const control = NodeProperties::GetControlInput(node);
// Extract constructor and original constructor function. // Extract constructor and original constructor function.
if (target_type.IsHeapConstant() && new_target_type.IsHeapConstant() && if (!target_type.IsHeapConstant() || !new_target_type.IsHeapConstant() ||
target_type.AsHeapConstant()->Value()->IsJSFunction() && !target_type.AsHeapConstant()->Ref().IsJSFunction() ||
new_target_type.AsHeapConstant()->Value()->IsJSFunction()) { !new_target_type.AsHeapConstant()->Ref().IsJSFunction()) {
Handle<JSFunction> constructor = return NoChange();
Handle<JSFunction>::cast(target_type.AsHeapConstant()->Value()); }
if (!constructor->IsConstructor()) return NoChange();
Handle<JSFunction> original_constructor =
Handle<JSFunction>::cast(new_target_type.AsHeapConstant()->Value());
if (!original_constructor->IsConstructor()) return NoChange();
// Check if we can inline the allocation. JSFunctionRef constructor =
if (IsAllocationInlineable(constructor, original_constructor)) { target_type.AsHeapConstant()->Ref().AsJSFunction();
// Force completion of inobject slack tracking before if (!constructor.IsConstructor()) return NoChange();
// generating code to finalize the instance size. JSFunctionRef original_constructor =
original_constructor->CompleteInobjectSlackTrackingIfActive(); new_target_type.AsHeapConstant()->Ref().AsJSFunction();
if (!original_constructor.IsConstructor()) return NoChange();
// Add a dependency on the {initial_map} to make sure that this code is // Check if we can inline the allocation.
// deoptimized whenever the {initial_map} changes. if (!IsAllocationInlineable(constructor, original_constructor,
Handle<Map> initial_map = js_heap_broker())) {
dependencies()->DependOnInitialMap(original_constructor); return NoChange();
int const instance_size = initial_map->instance_size(); }
// Emit code to allocate the JSObject instance for the // Add a dependency on the {initial_map} to make sure that this code is
// {original_constructor}. // deoptimized whenever the {initial_map} changes.
AllocationBuilder a(jsgraph(), js_heap_broker(), effect, control); MapRef initial_map =
a.Allocate(instance_size); original_constructor.DependOnInitialMap(js_heap_broker(), dependencies());
a.Store(AccessBuilder::ForMap(), initial_map);
a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), // Force completion of inobject slack tracking before
jsgraph()->EmptyFixedArrayConstant()); // generating code to finalize the instance size.
a.Store(AccessBuilder::ForJSObjectElements(), int const instance_size =
jsgraph()->EmptyFixedArrayConstant()); original_constructor.GetInstanceSizeWithFinishedSlackTracking();
for (int i = 0; i < initial_map->GetInObjectProperties(); ++i) {
a.Store( // Emit code to allocate the JSObject instance for the
AccessBuilder::ForJSObjectInObjectProperty(MapRef(initial_map), i), // {original_constructor}.
AllocationBuilder a(jsgraph(), js_heap_broker(), effect, control);
a.Allocate(instance_size);
a.Store(AccessBuilder::ForMap(), initial_map);
a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
jsgraph()->EmptyFixedArrayConstant());
a.Store(AccessBuilder::ForJSObjectElements(),
jsgraph()->EmptyFixedArrayConstant());
for (int i = 0; i < initial_map.GetInObjectProperties(); ++i) {
a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
jsgraph()->UndefinedConstant()); jsgraph()->UndefinedConstant());
}
RelaxControls(node);
a.FinishAndChange(node);
return Changed(node);
}
} }
return NoChange();
RelaxControls(node);
a.FinishAndChange(node);
return Changed(node);
} }
Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) { Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
...@@ -722,7 +730,9 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) { ...@@ -722,7 +730,9 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
DCHECK(original_constructor->IsConstructor()); DCHECK(original_constructor->IsConstructor());
// Check if we can inline the allocation. // Check if we can inline the allocation.
if (IsAllocationInlineable(constructor, original_constructor)) { if (IsAllocationInlineable(JSFunctionRef(constructor),
JSFunctionRef(original_constructor),
js_heap_broker())) {
// Force completion of inobject slack tracking before // Force completion of inobject slack tracking before
// generating code to finalize the instance size. // generating code to finalize the instance size.
original_constructor->CompleteInobjectSlackTrackingIfActive(); original_constructor->CompleteInobjectSlackTrackingIfActive();
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "src/compiler/js-heap-broker.h" #include "src/compiler/js-heap-broker.h"
#include "src/compiler/compilation-dependencies.h"
#include "src/objects-inl.h" #include "src/objects-inl.h"
#include "src/objects/js-regexp-inl.h" #include "src/objects/js-regexp-inl.h"
...@@ -165,6 +166,35 @@ BuiltinFunctionId JSFunctionRef::GetBuiltinFunctionId() const { ...@@ -165,6 +166,35 @@ BuiltinFunctionId JSFunctionRef::GetBuiltinFunctionId() const {
return object<JSFunction>()->shared()->builtin_function_id(); return object<JSFunction>()->shared()->builtin_function_id();
} }
bool JSFunctionRef::IsConstructor() const {
AllowHandleDereference allow_handle_dereference;
return object<JSFunction>()->IsConstructor();
}
MapRef JSFunctionRef::DependOnInitialMap(
const JSHeapBroker* broker, CompilationDependencies* dependencies) const {
AllowHandleDereference allow_handle_dereference;
Handle<Map> initial_map =
dependencies->DependOnInitialMap(object<JSFunction>());
return MapRef(initial_map);
}
int JSFunctionRef::GetInstanceSizeWithFinishedSlackTracking() const {
AllowHandleDereference allow_handle_dereference;
object<JSFunction>()->CompleteInobjectSlackTrackingIfActive();
return object<JSFunction>()->initial_map()->instance_size();
}
bool JSFunctionRef::has_initial_map() const {
AllowHandleDereference allow_handle_dereference;
return object<JSFunction>()->has_initial_map();
}
MapRef JSFunctionRef::initial_map(const JSHeapBroker* broker) const {
AllowHandleDereference allow_handle_dereference;
return MapRef(handle(object<JSFunction>()->initial_map(), broker->isolate()));
}
NameRef::NameRef(Handle<Object> object) : HeapObjectRef(object) { NameRef::NameRef(Handle<Object> object) : HeapObjectRef(object) {
AllowHandleDereference handle_dereference; AllowHandleDereference handle_dereference;
DCHECK(object->IsName()); DCHECK(object->IsName());
...@@ -373,6 +403,22 @@ FieldIndex MapRef::GetFieldIndexFor(int i) const { ...@@ -373,6 +403,22 @@ FieldIndex MapRef::GetFieldIndexFor(int i) const {
return FieldIndex::ForDescriptor(*object<Map>(), i); return FieldIndex::ForDescriptor(*object<Map>(), i);
} }
int MapRef::GetInObjectPropertyOffset(int i) const {
AllowHandleDereference allow_handle_dereference;
return object<Map>()->GetInObjectPropertyOffset(i);
}
bool MapRef::is_dictionary_map() const {
AllowHandleDereference allow_handle_dereference;
return object<Map>()->is_dictionary_map();
}
ObjectRef MapRef::constructor_or_backpointer(const JSHeapBroker* broker) const {
AllowHandleDereference allow_handle_dereference;
return ObjectRef(
handle(object<Map>()->constructor_or_backpointer(), broker->isolate()));
}
int MapRef::instance_size() const { int MapRef::instance_size() const {
AllowHandleDereference allow_handle_dereference; AllowHandleDereference allow_handle_dereference;
return object<Map>()->instance_size(); return object<Map>()->instance_size();
...@@ -404,22 +450,12 @@ bool MapRef::IsInobjectSlackTrackingInProgress() const { ...@@ -404,22 +450,12 @@ bool MapRef::IsInobjectSlackTrackingInProgress() const {
return object<Map>()->IsInobjectSlackTrackingInProgress(); return object<Map>()->IsInobjectSlackTrackingInProgress();
} }
bool MapRef::is_dictionary_map() const {
AllowHandleDereference allow_handle_dereference;
return object<Map>()->is_dictionary_map();
}
bool MapRef::IsFixedCowArrayMap(const JSHeapBroker* broker) const { bool MapRef::IsFixedCowArrayMap(const JSHeapBroker* broker) const {
AllowHandleDereference allow_handle_dereference; AllowHandleDereference allow_handle_dereference;
return *object<Map>() == return *object<Map>() ==
ReadOnlyRoots(broker->isolate()).fixed_cow_array_map(); ReadOnlyRoots(broker->isolate()).fixed_cow_array_map();
} }
int MapRef::GetInObjectPropertyOffset(int index) const {
AllowHandleDereference allow_handle_dereference;
return object<Map>()->GetInObjectPropertyOffset(index);
}
bool MapRef::has_prototype_slot() const { bool MapRef::has_prototype_slot() const {
AllowHandleDereference allow_handle_dereference; AllowHandleDereference allow_handle_dereference;
return object<Map>()->has_prototype_slot(); return object<Map>()->has_prototype_slot();
......
...@@ -14,6 +14,8 @@ namespace v8 { ...@@ -14,6 +14,8 @@ namespace v8 {
namespace internal { namespace internal {
namespace compiler { namespace compiler {
class CompilationDependencies;
enum class OddballType : uint8_t { enum class OddballType : uint8_t {
kNone, // Not an Oddball. kNone, // Not an Oddball.
kBoolean, // True or False. kBoolean, // True or False.
...@@ -163,8 +165,16 @@ class JSObjectRef : public HeapObjectRef { ...@@ -163,8 +165,16 @@ class JSObjectRef : public HeapObjectRef {
class JSFunctionRef : public JSObjectRef { class JSFunctionRef : public JSObjectRef {
public: public:
explicit JSFunctionRef(Handle<Object> object); explicit JSFunctionRef(Handle<Object> object);
bool HasBuiltinFunctionId() const; bool HasBuiltinFunctionId() const;
BuiltinFunctionId GetBuiltinFunctionId() const; BuiltinFunctionId GetBuiltinFunctionId() const;
bool IsConstructor() const;
bool has_initial_map() const;
MapRef initial_map(const JSHeapBroker* broker) const;
MapRef DependOnInitialMap(const JSHeapBroker* broker,
CompilationDependencies* dependencies) const;
int GetInstanceSizeWithFinishedSlackTracking() const;
}; };
class JSRegExpRef : public JSObjectRef { class JSRegExpRef : public JSObjectRef {
...@@ -260,15 +270,17 @@ class MapRef : public HeapObjectRef { ...@@ -260,15 +270,17 @@ class MapRef : public HeapObjectRef {
InstanceType instance_type() const; InstanceType instance_type() const;
int GetInObjectProperties() const; int GetInObjectProperties() const;
int NumberOfOwnDescriptors() const; int NumberOfOwnDescriptors() const;
PropertyDetails GetPropertyDetails(int i) const; PropertyDetails GetPropertyDetails(int i) const;
NameRef GetPropertyKey(const JSHeapBroker* broker, int i) const; NameRef GetPropertyKey(const JSHeapBroker* broker, int i) const;
FieldIndex GetFieldIndexFor(int i) const; FieldIndex GetFieldIndexFor(int i) const;
int GetInObjectPropertyOffset(int index) const; int GetInObjectPropertyOffset(int index) const;
bool is_dictionary_map() const;
ObjectRef constructor_or_backpointer(const JSHeapBroker* broker) const;
bool IsJSArrayMap() const; bool IsJSArrayMap() const;
bool IsFixedCowArrayMap(const JSHeapBroker* broker) const; bool IsFixedCowArrayMap(const JSHeapBroker* broker) const;
bool is_dictionary_map() const;
bool has_prototype_slot() const; bool has_prototype_slot() const;
......
...@@ -30,7 +30,10 @@ namespace compiler { ...@@ -30,7 +30,10 @@ namespace compiler {
class JSCreateLoweringTest : public TypedGraphTest { class JSCreateLoweringTest : public TypedGraphTest {
public: public:
JSCreateLoweringTest() JSCreateLoweringTest()
: TypedGraphTest(3), javascript_(zone()), deps_(isolate(), zone()) {} : TypedGraphTest(3),
javascript_(zone()),
deps_(isolate(), zone()),
handle_scope_(isolate()) {}
~JSCreateLoweringTest() override {} ~JSCreateLoweringTest() override {}
protected: protected:
...@@ -63,6 +66,7 @@ class JSCreateLoweringTest : public TypedGraphTest { ...@@ -63,6 +66,7 @@ class JSCreateLoweringTest : public TypedGraphTest {
private: private:
JSOperatorBuilder javascript_; JSOperatorBuilder javascript_;
CompilationDependencies deps_; CompilationDependencies deps_;
CanonicalHandleScope handle_scope_;
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment