summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/js-create-lowering.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/js-create-lowering.cc')
-rw-r--r--deps/v8/src/compiler/js-create-lowering.cc690
1 files changed, 315 insertions, 375 deletions
diff --git a/deps/v8/src/compiler/js-create-lowering.cc b/deps/v8/src/compiler/js-create-lowering.cc
index 87698565ef..a9ce42e1e2 100644
--- a/deps/v8/src/compiler/js-create-lowering.cc
+++ b/deps/v8/src/compiler/js-create-lowering.cc
@@ -4,12 +4,11 @@
#include "src/compiler/js-create-lowering.h"
-#include "src/allocation-site-scopes.h"
#include "src/code-factory.h"
-#include "src/compilation-dependencies.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/allocation-builder.h"
#include "src/compiler/common-operator.h"
+#include "src/compiler/compilation-dependencies.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/linkage.h"
@@ -20,7 +19,10 @@
#include "src/compiler/simplified-operator.h"
#include "src/compiler/state-values-utils.h"
#include "src/objects-inl.h"
+#include "src/objects/arguments.h"
#include "src/objects/hash-table-inl.h"
+#include "src/objects/js-promise.h"
+#include "src/objects/js-regexp-inl.h"
namespace v8 {
namespace internal {
@@ -39,11 +41,11 @@ Node* GetArgumentsFrameState(Node* frame_state) {
// Checks whether allocation using the given target and new.target can be
// inlined.
-bool IsAllocationInlineable(Handle<JSFunction> target,
- Handle<JSFunction> new_target) {
- return new_target->has_initial_map() &&
- !new_target->initial_map()->is_dictionary_map() &&
- new_target->initial_map()->constructor_or_backpointer() == *target;
+bool IsAllocationInlineable(const JSFunctionRef& target,
+ const JSFunctionRef& new_target) {
+ return new_target.has_initial_map() &&
+ !new_target.initial_map().is_dictionary_map() &&
+ new_target.initial_map().constructor_or_backpointer().equals(target);
}
// When initializing arrays, we'll unfold the loop if the number of
@@ -54,81 +56,6 @@ const int kElementLoopUnrollLimit = 16;
const int kFunctionContextAllocationLimit = 16;
const int kBlockContextAllocationLimit = 16;
-// Determines whether the given array or object literal boilerplate satisfies
-// all limits to be considered for fast deep-copying and computes the total
-// size of all objects that are part of the graph.
-bool IsFastLiteral(Handle<JSObject> boilerplate, int max_depth,
- int* max_properties) {
- DCHECK_GE(max_depth, 0);
- DCHECK_GE(*max_properties, 0);
-
- // Make sure the boilerplate map is not deprecated.
- if (!JSObject::TryMigrateInstance(boilerplate)) return false;
-
- // Check for too deep nesting.
- if (max_depth == 0) return false;
-
- // Check the elements.
- Isolate* const isolate = boilerplate->GetIsolate();
- Handle<FixedArrayBase> elements(boilerplate->elements(), isolate);
- if (elements->length() > 0 &&
- elements->map() != isolate->heap()->fixed_cow_array_map()) {
- if (boilerplate->HasSmiOrObjectElements()) {
- Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
- int length = elements->length();
- for (int i = 0; i < length; i++) {
- if ((*max_properties)-- == 0) return false;
- Handle<Object> value(fast_elements->get(i), isolate);
- if (value->IsJSObject()) {
- Handle<JSObject> value_object = Handle<JSObject>::cast(value);
- if (!IsFastLiteral(value_object, max_depth - 1, max_properties)) {
- return false;
- }
- }
- }
- } else if (boilerplate->HasDoubleElements()) {
- if (elements->Size() > kMaxRegularHeapObjectSize) return false;
- } else {
- return false;
- }
- }
-
- // TODO(turbofan): Do we want to support out-of-object properties?
- if (!(boilerplate->HasFastProperties() &&
- boilerplate->property_array()->length() == 0)) {
- return false;
- }
-
- // Check the in-object properties.
- Handle<DescriptorArray> descriptors(
- boilerplate->map()->instance_descriptors(), isolate);
- int limit = boilerplate->map()->NumberOfOwnDescriptors();
- for (int i = 0; i < limit; i++) {
- PropertyDetails details = descriptors->GetDetails(i);
- if (details.location() != kField) continue;
- DCHECK_EQ(kData, details.kind());
- if ((*max_properties)-- == 0) return false;
- FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i);
- if (boilerplate->IsUnboxedDoubleField(field_index)) continue;
- Handle<Object> value(boilerplate->RawFastPropertyAt(field_index), isolate);
- if (value->IsJSObject()) {
- Handle<JSObject> value_object = Handle<JSObject>::cast(value);
- if (!IsFastLiteral(value_object, max_depth - 1, max_properties)) {
- return false;
- }
- }
- }
- return true;
-}
-
-// Maximum depth and total number of elements and properties for literal
-// graphs to be considered for fast deep-copying. The limit is chosen to
-// match the maximum number of inobject properties, to ensure that the
-// performance of using object literals is not worse than using constructor
-// functions, see crbug.com/v8/6211 for details.
-const int kMaxFastLiteralDepth = 3;
-const int kMaxFastLiteralProperties = JSObject::kMaxInObjectProperties;
-
} // namespace
Reduction JSCreateLowering::Reduce(Node* node) {
@@ -183,6 +110,7 @@ Reduction JSCreateLowering::Reduce(Node* node) {
}
Reduction JSCreateLowering::ReduceJSCreate(Node* node) {
+ DisallowHeapAccess no_heap_access;
DCHECK_EQ(IrOpcode::kJSCreate, node->opcode());
Node* const target = NodeProperties::GetValueInput(node, 0);
Type const target_type = NodeProperties::GetType(target);
@@ -191,58 +119,62 @@ Reduction JSCreateLowering::ReduceJSCreate(Node* node) {
Node* const effect = NodeProperties::GetEffectInput(node);
Node* const control = NodeProperties::GetControlInput(node);
// Extract constructor and original constructor function.
- if (target_type.IsHeapConstant() && new_target_type.IsHeapConstant() &&
- target_type.AsHeapConstant()->Value()->IsJSFunction() &&
- new_target_type.AsHeapConstant()->Value()->IsJSFunction()) {
- Handle<JSFunction> constructor =
- 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();
+ if (!target_type.IsHeapConstant() || !new_target_type.IsHeapConstant() ||
+ !target_type.AsHeapConstant()->Ref().IsJSFunction() ||
+ !new_target_type.AsHeapConstant()->Ref().IsJSFunction()) {
+ return NoChange();
+ }
- // Check if we can inline the allocation.
- if (IsAllocationInlineable(constructor, original_constructor)) {
- // Force completion of inobject slack tracking before
- // generating code to finalize the instance size.
- original_constructor->CompleteInobjectSlackTrackingIfActive();
- Handle<Map> initial_map(original_constructor->initial_map(), isolate());
- int const instance_size = initial_map->instance_size();
+ JSFunctionRef constructor =
+ target_type.AsHeapConstant()->Ref().AsJSFunction();
+ if (!constructor.IsConstructor()) return NoChange();
+ JSFunctionRef original_constructor =
+ 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
- // deoptimized whenever the {initial_map} changes.
- dependencies()->AssumeInitialMapCantChange(initial_map);
+ // Check if we can inline the allocation.
+ if (!IsAllocationInlineable(constructor, original_constructor)) {
+ return NoChange();
+ }
- // Emit code to allocate the JSObject instance for the
- // {original_constructor}.
- AllocationBuilder a(jsgraph(), 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());
- }
- RelaxControls(node);
- a.FinishAndChange(node);
- return Changed(node);
- }
+ // Add a dependency on the {initial_map} to make sure that this code is
+ // deoptimized whenever the {initial_map} changes.
+ MapRef initial_map = dependencies()->DependOnInitialMap(original_constructor);
+
+ // Force completion of inobject slack tracking before
+ // generating code to finalize the instance size.
+ SlackTrackingResult slack_tracking_result =
+ original_constructor.FinishSlackTracking();
+
+ // Emit code to allocate the JSObject instance for the
+ // {original_constructor}.
+ AllocationBuilder a(jsgraph(), effect, control);
+ a.Allocate(slack_tracking_result.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 < slack_tracking_result.inobject_property_count; ++i) {
+ a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
+ jsgraph()->UndefinedConstant());
}
- return NoChange();
+
+ RelaxControls(node);
+ a.FinishAndChange(node);
+ return Changed(node);
}
Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
+ DisallowHeapAccess no_heap_access;
DCHECK_EQ(IrOpcode::kJSCreateArguments, node->opcode());
CreateArgumentsType type = CreateArgumentsTypeOf(node->op());
Node* const frame_state = NodeProperties::GetFrameStateInput(node);
Node* const outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
Node* const control = graph()->start();
FrameStateInfo state_info = FrameStateInfoOf(frame_state->op());
- Handle<SharedFunctionInfo> shared =
- state_info.shared_info().ToHandleChecked();
+ SharedFunctionInfoRef shared(js_heap_broker(),
+ state_info.shared_info().ToHandleChecked());
// Use the ArgumentsAccessStub for materializing both mapped and unmapped
// arguments object, but only for non-inlined (i.e. outermost) frames.
@@ -250,7 +182,7 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
switch (type) {
case CreateArgumentsType::kMappedArguments: {
// TODO(mstarzinger): Duplicate parameters are not handled yet.
- if (shared->has_duplicate_parameters()) return NoChange();
+ if (shared.has_duplicate_parameters()) return NoChange();
Node* const callee = NodeProperties::GetValueInput(node, 0);
Node* const context = NodeProperties::GetContextInput(node);
Node* effect = NodeProperties::GetEffectInput(node);
@@ -258,7 +190,7 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
graph()->NewNode(simplified()->ArgumentsFrame());
Node* const arguments_length = graph()->NewNode(
simplified()->ArgumentsLength(
- shared->internal_formal_parameter_count(), false),
+ shared.internal_formal_parameter_count(), false),
arguments_frame);
// Allocate the elements backing store.
bool has_aliased_arguments = false;
@@ -266,11 +198,10 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
effect, control, context, arguments_frame, arguments_length, shared,
&has_aliased_arguments);
// Load the arguments object map.
- Node* const arguments_map = jsgraph()->HeapConstant(
- handle(has_aliased_arguments
- ? native_context()->fast_aliased_arguments_map()
- : native_context()->sloppy_arguments_map(),
- isolate()));
+ Node* const arguments_map = jsgraph()->Constant(
+ has_aliased_arguments
+ ? native_context_ref().fast_aliased_arguments_map()
+ : native_context_ref().sloppy_arguments_map());
// Actually allocate and initialize the arguments object.
AllocationBuilder a(jsgraph(), effect, control);
Node* properties = jsgraph()->EmptyFixedArrayConstant();
@@ -291,15 +222,15 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
graph()->NewNode(simplified()->ArgumentsFrame());
Node* const arguments_length = graph()->NewNode(
simplified()->ArgumentsLength(
- shared->internal_formal_parameter_count(), false),
+ shared.internal_formal_parameter_count(), false),
arguments_frame);
// Allocate the elements backing store.
Node* const elements = effect =
graph()->NewNode(simplified()->NewArgumentsElements(0),
arguments_frame, arguments_length, effect);
// Load the arguments object map.
- Node* const arguments_map = jsgraph()->HeapConstant(
- handle(native_context()->strict_arguments_map(), isolate()));
+ Node* const arguments_map =
+ jsgraph()->Constant(native_context_ref().strict_arguments_map());
// Actually allocate and initialize the arguments object.
AllocationBuilder a(jsgraph(), effect, control);
Node* properties = jsgraph()->EmptyFixedArrayConstant();
@@ -319,7 +250,7 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
graph()->NewNode(simplified()->ArgumentsFrame());
Node* const rest_length = graph()->NewNode(
simplified()->ArgumentsLength(
- shared->internal_formal_parameter_count(), true),
+ shared.internal_formal_parameter_count(), true),
arguments_frame);
// Allocate the elements backing store. Since NewArgumentsElements
// copies from the end of the arguments adapter frame, this is a suffix
@@ -328,8 +259,8 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
graph()->NewNode(simplified()->NewArgumentsElements(0),
arguments_frame, rest_length, effect);
// Load the JSArray object map.
- Node* const jsarray_map = jsgraph()->HeapConstant(handle(
- native_context()->js_array_fast_elements_map_index(), isolate()));
+ Node* const jsarray_map = jsgraph()->Constant(
+ native_context_ref().js_array_fast_elements_map_index());
// Actually allocate and initialize the jsarray.
AllocationBuilder a(jsgraph(), effect, control);
Node* properties = jsgraph()->EmptyFixedArrayConstant();
@@ -353,7 +284,7 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
Node* const context = NodeProperties::GetContextInput(node);
Node* effect = NodeProperties::GetEffectInput(node);
// TODO(mstarzinger): Duplicate parameters are not handled yet.
- if (shared->has_duplicate_parameters()) return NoChange();
+ if (shared.has_duplicate_parameters()) return NoChange();
// Choose the correct frame state and frame state info depending on
// whether there conceptually is an arguments adaptor frame in the call
// chain.
@@ -372,10 +303,10 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
effect, control, args_state, context, shared, &has_aliased_arguments);
effect = elements->op()->EffectOutputCount() > 0 ? elements : effect;
// Load the arguments object map.
- Node* const arguments_map = jsgraph()->HeapConstant(handle(
- has_aliased_arguments ? native_context()->fast_aliased_arguments_map()
- : native_context()->sloppy_arguments_map(),
- isolate()));
+ Node* const arguments_map = jsgraph()->Constant(
+ has_aliased_arguments
+ ? native_context_ref().fast_aliased_arguments_map()
+ : native_context_ref().sloppy_arguments_map());
// Actually allocate and initialize the arguments object.
AllocationBuilder a(jsgraph(), effect, control);
Node* properties = jsgraph()->EmptyFixedArrayConstant();
@@ -410,8 +341,8 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
Node* const elements = AllocateArguments(effect, control, args_state);
effect = elements->op()->EffectOutputCount() > 0 ? elements : effect;
// Load the arguments object map.
- Node* const arguments_map = jsgraph()->HeapConstant(
- handle(native_context()->strict_arguments_map(), isolate()));
+ Node* const arguments_map =
+ jsgraph()->Constant(native_context_ref().strict_arguments_map());
// Actually allocate and initialize the arguments object.
AllocationBuilder a(jsgraph(), effect, control);
Node* properties = jsgraph()->EmptyFixedArrayConstant();
@@ -426,7 +357,7 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
a.FinishAndChange(node);
return Changed(node);
} else if (type == CreateArgumentsType::kRestParameter) {
- int start_index = shared->internal_formal_parameter_count();
+ int start_index = shared.internal_formal_parameter_count();
// Use inline allocation for all unmapped arguments objects within inlined
// (i.e. non-outermost) frames, independent of the object size.
Node* effect = NodeProperties::GetEffectInput(node);
@@ -447,8 +378,8 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
AllocateRestArguments(effect, control, args_state, start_index);
effect = elements->op()->EffectOutputCount() > 0 ? elements : effect;
// Load the JSArray object map.
- Node* const jsarray_map = jsgraph()->HeapConstant(handle(
- native_context()->js_array_fast_elements_map_index(), isolate()));
+ Node* const jsarray_map = jsgraph()->Constant(
+ native_context_ref().js_array_fast_elements_map_index());
// Actually allocate and initialize the jsarray.
AllocationBuilder a(jsgraph(), effect, control);
Node* properties = jsgraph()->EmptyFixedArrayConstant();
@@ -473,6 +404,7 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
}
Reduction JSCreateLowering::ReduceJSCreateGeneratorObject(Node* node) {
+ DisallowHeapAccess no_heap_access;
DCHECK_EQ(IrOpcode::kJSCreateGeneratorObject, node->opcode());
Node* const closure = NodeProperties::GetValueInput(node, 0);
Node* const receiver = NodeProperties::GetValueInput(node, 1);
@@ -481,36 +413,39 @@ Reduction JSCreateLowering::ReduceJSCreateGeneratorObject(Node* node) {
Node* effect = NodeProperties::GetEffectInput(node);
Node* const control = NodeProperties::GetControlInput(node);
if (closure_type.IsHeapConstant()) {
- DCHECK(closure_type.AsHeapConstant()->Value()->IsJSFunction());
- Handle<JSFunction> js_function =
- Handle<JSFunction>::cast(closure_type.AsHeapConstant()->Value());
- JSFunction::EnsureHasInitialMap(js_function);
+ DCHECK(closure_type.AsHeapConstant()->Ref().IsJSFunction());
+ JSFunctionRef js_function =
+ closure_type.AsHeapConstant()->Ref().AsJSFunction();
+ js_function.EnsureHasInitialMap();
// Force completion of inobject slack tracking before
// generating code to finalize the instance size.
- js_function->CompleteInobjectSlackTrackingIfActive();
- Handle<Map> initial_map(js_function->initial_map(), isolate());
- DCHECK(initial_map->instance_type() == JS_GENERATOR_OBJECT_TYPE ||
- initial_map->instance_type() == JS_ASYNC_GENERATOR_OBJECT_TYPE);
+ SlackTrackingResult slack_tracking_result =
+ js_function.FinishSlackTracking();
// Add a dependency on the {initial_map} to make sure that this code is
// deoptimized whenever the {initial_map} changes.
- dependencies()->AssumeInitialMapCantChange(initial_map);
+ MapRef initial_map = dependencies()->DependOnInitialMap(js_function);
+ DCHECK(initial_map.instance_type() == JS_GENERATOR_OBJECT_TYPE ||
+ initial_map.instance_type() == JS_ASYNC_GENERATOR_OBJECT_TYPE);
// Allocate a register file.
- DCHECK(js_function->shared()->HasBytecodeArray());
- int size = js_function->shared()->GetBytecodeArray()->register_count();
+ SharedFunctionInfoRef shared = js_function.shared();
+ DCHECK(shared.HasBytecodeArray());
+ int parameter_count_no_receiver = shared.internal_formal_parameter_count();
+ int size =
+ parameter_count_no_receiver + shared.GetBytecodeArrayRegisterCount();
AllocationBuilder ab(jsgraph(), effect, control);
ab.AllocateArray(size, factory()->fixed_array_map());
for (int i = 0; i < size; ++i) {
ab.Store(AccessBuilder::ForFixedArraySlot(i),
jsgraph()->UndefinedConstant());
}
- Node* register_file = effect = ab.Finish();
+ Node* parameters_and_registers = effect = ab.Finish();
// Emit code to allocate the JS[Async]GeneratorObject instance.
AllocationBuilder a(jsgraph(), effect, control);
- a.Allocate(initial_map->instance_size());
+ a.Allocate(slack_tracking_result.instance_size);
Node* empty_fixed_array = jsgraph()->EmptyFixedArrayConstant();
Node* undefined = jsgraph()->UndefinedConstant();
a.Store(AccessBuilder::ForMap(), initial_map);
@@ -524,16 +459,17 @@ Reduction JSCreateLowering::ReduceJSCreateGeneratorObject(Node* node) {
jsgraph()->Constant(JSGeneratorObject::kNext));
a.Store(AccessBuilder::ForJSGeneratorObjectContinuation(),
jsgraph()->Constant(JSGeneratorObject::kGeneratorExecuting));
- a.Store(AccessBuilder::ForJSGeneratorObjectRegisterFile(), register_file);
+ a.Store(AccessBuilder::ForJSGeneratorObjectParametersAndRegisters(),
+ parameters_and_registers);
- if (initial_map->instance_type() == JS_ASYNC_GENERATOR_OBJECT_TYPE) {
+ if (initial_map.instance_type() == JS_ASYNC_GENERATOR_OBJECT_TYPE) {
a.Store(AccessBuilder::ForJSAsyncGeneratorObjectQueue(), undefined);
a.Store(AccessBuilder::ForJSAsyncGeneratorObjectIsAwaiting(),
jsgraph()->ZeroConstant());
}
// Handle in-object properties, too.
- for (int i = 0; i < initial_map->GetInObjectProperties(); ++i) {
+ for (int i = 0; i < slack_tracking_result.inobject_property_count; ++i) {
a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
undefined);
}
@@ -555,8 +491,9 @@ Reduction JSCreateLowering::ReduceNewArray(Node* node, Node* length,
// Constructing an Array via new Array(N) where N is an unsigned
// integer, always creates a holey backing store.
if (!IsHoleyElementsKind(initial_map->elements_kind())) {
- initial_map = Map::AsElementsKind(
- initial_map, GetHoleyElementsKind(initial_map->elements_kind()));
+ initial_map =
+ Map::AsElementsKind(isolate(), initial_map,
+ GetHoleyElementsKind(initial_map->elements_kind()));
}
// Check that the {limit} is an unsigned integer in the valid range.
@@ -584,7 +521,8 @@ Reduction JSCreateLowering::ReduceNewArray(Node* node, Node* length,
a.Store(AccessBuilder::ForJSArrayLength(initial_map->elements_kind()),
length);
for (int i = 0; i < initial_map->GetInObjectProperties(); ++i) {
- a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
+ a.Store(AccessBuilder::ForJSObjectInObjectProperty(
+ MapRef(js_heap_broker(), initial_map), i),
jsgraph()->UndefinedConstant());
}
RelaxControls(node);
@@ -607,7 +545,7 @@ Reduction JSCreateLowering::ReduceNewArray(Node* node, Node* length,
ElementsKind elements_kind = initial_map->elements_kind();
if (NodeProperties::GetType(length).Max() > 0.0) {
elements_kind = GetHoleyElementsKind(elements_kind);
- initial_map = Map::AsElementsKind(initial_map, elements_kind);
+ initial_map = Map::AsElementsKind(isolate(), initial_map, elements_kind);
}
DCHECK(IsFastElementsKind(elements_kind));
@@ -629,7 +567,8 @@ Reduction JSCreateLowering::ReduceNewArray(Node* node, Node* length,
a.Store(AccessBuilder::ForJSObjectElements(), elements);
a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length);
for (int i = 0; i < initial_map->GetInObjectProperties(); ++i) {
- a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
+ a.Store(AccessBuilder::ForJSObjectInObjectProperty(
+ MapRef(js_heap_broker(), initial_map), i),
jsgraph()->UndefinedConstant());
}
RelaxControls(node);
@@ -685,7 +624,8 @@ Reduction JSCreateLowering::ReduceNewArray(Node* node,
a.Store(AccessBuilder::ForJSObjectElements(), elements);
a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length);
for (int i = 0; i < initial_map->GetInObjectProperties(); ++i) {
- a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
+ a.Store(AccessBuilder::ForJSObjectInObjectProperty(
+ MapRef(js_heap_broker(), initial_map), i),
jsgraph()->UndefinedConstant());
}
RelaxControls(node);
@@ -718,35 +658,35 @@ Reduction JSCreateLowering::ReduceNewArrayToStubCall(
: Operator::kNoDeopt | Operator::kNoWrite;
if (arity == 0) {
- ArrayNoArgumentConstructorStub stub(isolate(), elements_kind,
- override_mode);
+ Callable callable = CodeFactory::ArrayNoArgumentConstructor(
+ isolate(), elements_kind, override_mode);
auto call_descriptor = Linkage::GetStubCallDescriptor(
- isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(),
- arity + 1, CallDescriptor::kNeedsFrameState, properties);
- node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode()));
+ graph()->zone(), callable.descriptor(), arity + 1,
+ CallDescriptor::kNeedsFrameState, properties);
+ node->ReplaceInput(0, jsgraph()->HeapConstant(callable.code()));
node->InsertInput(graph()->zone(), 2, type_info);
node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(arity));
node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
} else if (arity == 1) {
// Require elements kind to "go holey".
- ArraySingleArgumentConstructorStub stub(
+ Callable callable = CodeFactory::ArraySingleArgumentConstructor(
isolate(), GetHoleyElementsKind(elements_kind), override_mode);
auto call_descriptor = Linkage::GetStubCallDescriptor(
- isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(),
- arity + 1, CallDescriptor::kNeedsFrameState, properties);
- node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode()));
+ graph()->zone(), callable.descriptor(), arity + 1,
+ CallDescriptor::kNeedsFrameState, properties);
+ node->ReplaceInput(0, jsgraph()->HeapConstant(callable.code()));
node->InsertInput(graph()->zone(), 2, type_info);
node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(arity));
node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
} else {
DCHECK_GT(arity, 1);
- ArrayNArgumentsConstructorStub stub(isolate());
+ Handle<Code> code = BUILTIN_CODE(isolate(), ArrayNArgumentsConstructor);
auto call_descriptor = Linkage::GetStubCallDescriptor(
- isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(),
- arity + 1, CallDescriptor::kNeedsFrameState);
- node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode()));
+ graph()->zone(), ArrayNArgumentsConstructorDescriptor{}, arity + 1,
+ CallDescriptor::kNeedsFrameState);
+ node->ReplaceInput(0, jsgraph()->HeapConstant(code));
node->InsertInput(graph()->zone(), 2, type_info);
node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(arity));
node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
@@ -764,9 +704,10 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
Handle<JSFunction> constructor(native_context()->array_function(), isolate());
Node* target = NodeProperties::GetValueInput(node, 0);
Node* new_target = NodeProperties::GetValueInput(node, 1);
- Type new_target_type = (target == new_target)
- ? Type::HeapConstant(constructor, zone())
- : NodeProperties::GetType(new_target);
+ Type new_target_type =
+ (target == new_target)
+ ? Type::HeapConstant(js_heap_broker(), constructor, zone())
+ : NodeProperties::GetType(new_target);
// Extract original constructor function.
if (new_target_type.IsHeapConstant() &&
@@ -777,15 +718,17 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
DCHECK(original_constructor->IsConstructor());
// Check if we can inline the allocation.
- if (IsAllocationInlineable(constructor, original_constructor)) {
+ if (IsAllocationInlineable(
+ JSFunctionRef(js_heap_broker(), constructor),
+ JSFunctionRef(js_heap_broker(), original_constructor))) {
// Force completion of inobject slack tracking before
// generating code to finalize the instance size.
original_constructor->CompleteInobjectSlackTrackingIfActive();
- Handle<Map> initial_map(original_constructor->initial_map(), isolate());
// Add a dependency on the {initial_map} to make sure that this code is
// deoptimized whenever the {initial_map} changes.
- dependencies()->AssumeInitialMapCantChange(initial_map);
+ MapRef initial_map = dependencies()->DependOnInitialMap(
+ JSFunctionRef(js_heap_broker(), original_constructor));
// Tells whether we are protected by either the {site} or a
// protector cell to do certain speculative optimizations.
@@ -794,14 +737,16 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
// Check if we have a feedback {site} on the {node}.
if (!site.is_null()) {
ElementsKind elements_kind = site->GetElementsKind();
- if (initial_map->elements_kind() != elements_kind) {
- initial_map = Map::AsElementsKind(initial_map, elements_kind);
+ if (initial_map.elements_kind() != elements_kind) {
+ initial_map =
+ MapRef(js_heap_broker(),
+ Map::AsElementsKind(isolate(), initial_map.object<Map>(),
+ elements_kind));
}
can_inline_call = site->CanInlineCall();
- pretenure = site->GetPretenureMode();
-
- dependencies()->AssumeTransitionStable(site);
- dependencies()->AssumeTenuringDecision(site);
+ auto site_ref = AllocationSiteRef(js_heap_broker(), site);
+ pretenure = dependencies()->DependOnPretenureMode(site_ref);
+ dependencies()->DependOnElementsKind(site_ref);
} else {
can_inline_call = isolate()->IsArrayConstructorIntact();
}
@@ -809,30 +754,36 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
if (arity == 0) {
Node* length = jsgraph()->ZeroConstant();
int capacity = JSArray::kPreallocatedArrayElements;
- return ReduceNewArray(node, length, capacity, initial_map, pretenure);
+ return ReduceNewArray(node, length, capacity, initial_map.object<Map>(),
+ pretenure);
} else if (arity == 1) {
Node* length = NodeProperties::GetValueInput(node, 2);
Type length_type = NodeProperties::GetType(length);
if (!length_type.Maybe(Type::Number())) {
// Handle the single argument case, where we know that the value
// cannot be a valid Array length.
- ElementsKind elements_kind = initial_map->elements_kind();
+ ElementsKind elements_kind = initial_map.elements_kind();
elements_kind = GetMoreGeneralElementsKind(
elements_kind, IsHoleyElementsKind(elements_kind)
? HOLEY_ELEMENTS
: PACKED_ELEMENTS);
- initial_map = Map::AsElementsKind(initial_map, elements_kind);
- return ReduceNewArray(node, std::vector<Node*>{length}, initial_map,
- pretenure);
+ initial_map =
+ MapRef(js_heap_broker(),
+ Map::AsElementsKind(isolate(), initial_map.object<Map>(),
+ elements_kind));
+ return ReduceNewArray(node, std::vector<Node*>{length},
+ initial_map.object<Map>(), pretenure);
}
if (length_type.Is(Type::SignedSmall()) && length_type.Min() >= 0 &&
length_type.Max() <= kElementLoopUnrollLimit &&
length_type.Min() == length_type.Max()) {
int capacity = static_cast<int>(length_type.Max());
- return ReduceNewArray(node, length, capacity, initial_map, pretenure);
+ return ReduceNewArray(node, length, capacity,
+ initial_map.object<Map>(), pretenure);
}
if (length_type.Maybe(Type::UnsignedSmall()) && can_inline_call) {
- return ReduceNewArray(node, length, initial_map, pretenure);
+ return ReduceNewArray(node, length, initial_map.object<Map>(),
+ pretenure);
}
} else if (arity <= JSArray::kInitialMaxFastElementArray) {
// Gather the values to store into the newly created array.
@@ -856,7 +807,7 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
}
// Try to figure out the ideal elements kind statically.
- ElementsKind elements_kind = initial_map->elements_kind();
+ ElementsKind elements_kind = initial_map.elements_kind();
if (values_all_smis) {
// Smis can be stored with any elements kind.
} else if (values_all_numbers) {
@@ -877,9 +828,13 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
// we cannot inline this invocation of the Array constructor here.
return NoChange();
}
- initial_map = Map::AsElementsKind(initial_map, elements_kind);
+ initial_map =
+ MapRef(js_heap_broker(),
+ Map::AsElementsKind(isolate(), initial_map.object<Map>(),
+ elements_kind));
- return ReduceNewArray(node, values, initial_map, pretenure);
+ return ReduceNewArray(node, values, initial_map.object<Map>(),
+ pretenure);
}
}
}
@@ -891,6 +846,7 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
}
Reduction JSCreateLowering::ReduceJSCreateArrayIterator(Node* node) {
+ DisallowHeapAccess no_heap_access;
DCHECK_EQ(IrOpcode::kJSCreateArrayIterator, node->opcode());
CreateArrayIteratorParameters const& p =
CreateArrayIteratorParametersOf(node->op());
@@ -902,7 +858,7 @@ Reduction JSCreateLowering::ReduceJSCreateArrayIterator(Node* node) {
AllocationBuilder a(jsgraph(), effect, control);
a.Allocate(JSArrayIterator::kSize, NOT_TENURED, Type::OtherObject());
a.Store(AccessBuilder::ForMap(),
- handle(native_context()->initial_array_iterator_map(), isolate()));
+ native_context_ref().initial_array_iterator_map());
a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
jsgraph()->EmptyFixedArrayConstant());
a.Store(AccessBuilder::ForJSObjectElements(),
@@ -919,27 +875,28 @@ Reduction JSCreateLowering::ReduceJSCreateArrayIterator(Node* node) {
namespace {
-Context::Field ContextFieldForCollectionIterationKind(
- CollectionKind collection_kind, IterationKind iteration_kind) {
+MapRef MapForCollectionIterationKind(const NativeContextRef& native_context,
+ CollectionKind collection_kind,
+ IterationKind iteration_kind) {
switch (collection_kind) {
case CollectionKind::kSet:
switch (iteration_kind) {
case IterationKind::kKeys:
UNREACHABLE();
case IterationKind::kValues:
- return Context::SET_VALUE_ITERATOR_MAP_INDEX;
+ return native_context.set_value_iterator_map();
case IterationKind::kEntries:
- return Context::SET_KEY_VALUE_ITERATOR_MAP_INDEX;
+ return native_context.set_key_value_iterator_map();
}
break;
case CollectionKind::kMap:
switch (iteration_kind) {
case IterationKind::kKeys:
- return Context::MAP_KEY_ITERATOR_MAP_INDEX;
+ return native_context.map_key_iterator_map();
case IterationKind::kValues:
- return Context::MAP_VALUE_ITERATOR_MAP_INDEX;
+ return native_context.map_value_iterator_map();
case IterationKind::kEntries:
- return Context::MAP_KEY_VALUE_ITERATOR_MAP_INDEX;
+ return native_context.map_key_value_iterator_map();
}
break;
}
@@ -949,6 +906,7 @@ Context::Field ContextFieldForCollectionIterationKind(
} // namespace
Reduction JSCreateLowering::ReduceJSCreateCollectionIterator(Node* node) {
+ DisallowHeapAccess no_heap_access;
DCHECK_EQ(IrOpcode::kJSCreateCollectionIterator, node->opcode());
CreateCollectionIteratorParameters const& p =
CreateCollectionIteratorParametersOf(node->op());
@@ -965,9 +923,8 @@ Reduction JSCreateLowering::ReduceJSCreateCollectionIterator(Node* node) {
AllocationBuilder a(jsgraph(), effect, control);
a.Allocate(JSCollectionIterator::kSize, NOT_TENURED, Type::OtherObject());
a.Store(AccessBuilder::ForMap(),
- handle(native_context()->get(ContextFieldForCollectionIterationKind(
- p.collection_kind(), p.iteration_kind())),
- isolate()));
+ MapForCollectionIterationKind(
+ native_context_ref(), p.collection_kind(), p.iteration_kind()));
a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
jsgraph()->EmptyFixedArrayConstant());
a.Store(AccessBuilder::ForJSObjectElements(),
@@ -981,11 +938,12 @@ Reduction JSCreateLowering::ReduceJSCreateCollectionIterator(Node* node) {
}
Reduction JSCreateLowering::ReduceJSCreateBoundFunction(Node* node) {
+ DisallowHeapAccess no_heap_access;
DCHECK_EQ(IrOpcode::kJSCreateBoundFunction, node->opcode());
CreateBoundFunctionParameters const& p =
CreateBoundFunctionParametersOf(node->op());
int const arity = static_cast<int>(p.arity());
- Handle<Map> const map = p.map();
+ MapRef const map(js_heap_broker(), p.map());
Node* bound_target_function = NodeProperties::GetValueInput(node, 0);
Node* bound_this = NodeProperties::GetValueInput(node, 1);
Node* effect = NodeProperties::GetEffectInput(node);
@@ -1021,11 +979,12 @@ Reduction JSCreateLowering::ReduceJSCreateBoundFunction(Node* node) {
}
Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) {
+ DisallowHeapAccess no_heap_access;
DCHECK_EQ(IrOpcode::kJSCreateClosure, node->opcode());
CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
- Handle<SharedFunctionInfo> shared = p.shared_info();
- Handle<FeedbackCell> feedback_cell = p.feedback_cell();
- Handle<Code> code = p.code();
+ SharedFunctionInfoRef shared(js_heap_broker(), p.shared_info());
+ HeapObjectRef feedback_cell(js_heap_broker(), p.feedback_cell());
+ HeapObjectRef code(js_heap_broker(), p.code());
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* context = NodeProperties::GetContextInput(node);
@@ -1033,16 +992,15 @@ Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) {
// Use inline allocation of closures only for instantiation sites that have
// seen more than one instantiation, this simplifies the generated code and
// also serves as a heuristic of which allocation sites benefit from it.
- if (feedback_cell->map() != isolate()->heap()->many_closures_cell_map()) {
- // The generic path can only create closures for user functions.
- DCHECK_EQ(isolate()->builtins()->builtin(Builtins::kCompileLazy), *code);
+ if (!feedback_cell.map().equals(
+ MapRef(js_heap_broker(), factory()->many_closures_cell_map()))) {
return NoChange();
}
- Handle<Map> function_map(
- Map::cast(native_context()->get(shared->function_map_index())));
- DCHECK(!function_map->IsInobjectSlackTrackingInProgress());
- DCHECK(!function_map->is_dictionary_map());
+ MapRef function_map =
+ native_context_ref().GetFunctionMapFromIndex(shared.function_map_index());
+ DCHECK(!function_map.IsInobjectSlackTrackingInProgress());
+ DCHECK(!function_map.is_dictionary_map());
// TODO(turbofan): We should use the pretenure flag from {p} here,
// but currently the heuristic in the parser works against us, as
@@ -1058,7 +1016,7 @@ Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) {
// Emit code to allocate the JSFunction instance.
STATIC_ASSERT(JSFunction::kSizeWithoutPrototype == 7 * kPointerSize);
AllocationBuilder a(jsgraph(), effect, control);
- a.Allocate(function_map->instance_size(), pretenure, Type::Function());
+ a.Allocate(function_map.instance_size(), pretenure, Type::Function());
a.Store(AccessBuilder::ForMap(), function_map);
a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
jsgraph()->EmptyFixedArrayConstant());
@@ -1069,12 +1027,12 @@ Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) {
a.Store(AccessBuilder::ForJSFunctionFeedbackCell(), feedback_cell);
a.Store(AccessBuilder::ForJSFunctionCode(), code);
STATIC_ASSERT(JSFunction::kSizeWithoutPrototype == 7 * kPointerSize);
- if (function_map->has_prototype_slot()) {
+ if (function_map.has_prototype_slot()) {
a.Store(AccessBuilder::ForJSFunctionPrototypeOrInitialMap(),
jsgraph()->TheHoleConstant());
STATIC_ASSERT(JSFunction::kSizeWithPrototype == 8 * kPointerSize);
}
- for (int i = 0; i < function_map->GetInObjectProperties(); i++) {
+ for (int i = 0; i < function_map.GetInObjectProperties(); i++) {
a.Store(AccessBuilder::ForJSObjectInObjectProperty(function_map, i),
jsgraph()->UndefinedConstant());
}
@@ -1084,13 +1042,14 @@ Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) {
}
Reduction JSCreateLowering::ReduceJSCreateIterResultObject(Node* node) {
+ DisallowHeapAccess no_heap_access;
DCHECK_EQ(IrOpcode::kJSCreateIterResultObject, node->opcode());
Node* value = NodeProperties::GetValueInput(node, 0);
Node* done = NodeProperties::GetValueInput(node, 1);
Node* effect = NodeProperties::GetEffectInput(node);
- Node* iterator_result_map = jsgraph()->HeapConstant(
- handle(native_context()->iterator_result_map(), isolate()));
+ Node* iterator_result_map =
+ jsgraph()->Constant(native_context_ref().iterator_result_map());
// Emit code to allocate the JSIteratorResult instance.
AllocationBuilder a(jsgraph(), effect, graph()->start());
@@ -1108,12 +1067,12 @@ Reduction JSCreateLowering::ReduceJSCreateIterResultObject(Node* node) {
}
Reduction JSCreateLowering::ReduceJSCreateStringIterator(Node* node) {
+ DisallowHeapAccess no_heap_access;
DCHECK_EQ(IrOpcode::kJSCreateStringIterator, node->opcode());
Node* string = NodeProperties::GetValueInput(node, 0);
Node* effect = NodeProperties::GetEffectInput(node);
- Node* map = jsgraph()->HeapConstant(
- handle(native_context()->string_iterator_map(), isolate()));
+ Node* map = jsgraph()->Constant(native_context_ref().string_iterator_map());
// Allocate new iterator and attach the iterator to this string.
AllocationBuilder a(jsgraph(), effect, graph()->start());
a.Allocate(JSStringIterator::kSize, NOT_TENURED, Type::OtherObject());
@@ -1130,13 +1089,14 @@ Reduction JSCreateLowering::ReduceJSCreateStringIterator(Node* node) {
}
Reduction JSCreateLowering::ReduceJSCreateKeyValueArray(Node* node) {
+ DisallowHeapAccess no_heap_access;
DCHECK_EQ(IrOpcode::kJSCreateKeyValueArray, node->opcode());
Node* key = NodeProperties::GetValueInput(node, 0);
Node* value = NodeProperties::GetValueInput(node, 1);
Node* effect = NodeProperties::GetEffectInput(node);
- Node* array_map = jsgraph()->HeapConstant(
- handle(native_context()->js_array_fast_elements_map_index()));
+ Node* array_map = jsgraph()->Constant(
+ native_context_ref().js_array_fast_elements_map_index());
Node* properties = jsgraph()->EmptyFixedArrayConstant();
Node* length = jsgraph()->Constant(2);
@@ -1160,13 +1120,14 @@ Reduction JSCreateLowering::ReduceJSCreateKeyValueArray(Node* node) {
}
Reduction JSCreateLowering::ReduceJSCreatePromise(Node* node) {
+ DisallowHeapAccess no_heap_access;
DCHECK_EQ(IrOpcode::kJSCreatePromise, node->opcode());
Node* effect = NodeProperties::GetEffectInput(node);
- Handle<Map> promise_map(native_context()->promise_function()->initial_map());
+ MapRef promise_map = native_context_ref().promise_function_initial_map();
AllocationBuilder a(jsgraph(), effect, graph()->start());
- a.Allocate(promise_map->instance_size());
+ a.Allocate(promise_map.instance_size());
a.Store(AccessBuilder::ForMap(), promise_map);
a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
jsgraph()->EmptyFixedArrayConstant());
@@ -1194,18 +1155,19 @@ Reduction JSCreateLowering::ReduceJSCreateLiteralArrayOrObject(Node* node) {
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
- Handle<Object> feedback(
- p.feedback().vector()->Get(p.feedback().slot())->ToObject(), isolate());
- if (feedback->IsAllocationSite()) {
- Handle<AllocationSite> site = Handle<AllocationSite>::cast(feedback);
- Handle<JSObject> boilerplate(site->boilerplate(), isolate());
- int max_properties = kMaxFastLiteralProperties;
- if (IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) {
- AllocationSiteUsageContext site_context(isolate(), site, false);
- site_context.EnterNewScope();
+ FeedbackVectorRef feedback_vector(js_heap_broker(), p.feedback().vector());
+ ObjectRef feedback = feedback_vector.get(p.feedback().slot());
+ if (feedback.IsAllocationSite()) {
+ AllocationSiteRef site = feedback.AsAllocationSite();
+ if (site.IsFastLiteral()) {
+ PretenureFlag pretenure = NOT_TENURED;
+ if (FLAG_allocation_site_pretenuring) {
+ pretenure = dependencies()->DependOnPretenureMode(site);
+ }
+ dependencies()->DependOnElementsKinds(site);
+ JSObjectRef boilerplate = site.boilerplate();
Node* value = effect =
- AllocateFastLiteral(effect, control, boilerplate, &site_context);
- site_context.ExitScope(site, boilerplate);
+ AllocateFastLiteral(effect, control, boilerplate, pretenure);
ReplaceWithValue(node, value, effect, control);
return Replace(value);
}
@@ -1224,9 +1186,10 @@ Reduction JSCreateLowering::ReduceJSCreateEmptyLiteralArray(Node* node) {
Handle<Map> const initial_map(
native_context()->GetInitialJSArrayMap(site->GetElementsKind()),
isolate());
- PretenureFlag const pretenure = site->GetPretenureMode();
- dependencies()->AssumeTransitionStable(site);
- dependencies()->AssumeTenuringDecision(site);
+ auto site_ref = AllocationSiteRef(js_heap_broker(), site);
+ PretenureFlag const pretenure =
+ dependencies()->DependOnPretenureMode(site_ref);
+ dependencies()->DependOnElementsKind(site_ref);
Node* length = jsgraph()->ZeroConstant();
return ReduceNewArray(node, length, 0, initial_map, pretenure);
}
@@ -1255,7 +1218,8 @@ Reduction JSCreateLowering::ReduceJSCreateEmptyLiteralObject(Node* node) {
a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
a.Store(AccessBuilder::ForJSObjectElements(), elements);
for (int i = 0; i < map->GetInObjectProperties(); i++) {
- a.Store(AccessBuilder::ForJSObjectInObjectProperty(map, i),
+ a.Store(AccessBuilder::ForJSObjectInObjectProperty(
+ MapRef(js_heap_broker(), map), i),
jsgraph()->UndefinedConstant());
}
@@ -1265,15 +1229,16 @@ Reduction JSCreateLowering::ReduceJSCreateEmptyLiteralObject(Node* node) {
}
Reduction JSCreateLowering::ReduceJSCreateLiteralRegExp(Node* node) {
+ DisallowHeapAccess no_heap_access;
DCHECK_EQ(IrOpcode::kJSCreateLiteralRegExp, node->opcode());
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
- Handle<Object> feedback(
- p.feedback().vector()->Get(p.feedback().slot())->ToObject(), isolate());
- if (feedback->IsJSRegExp()) {
- Handle<JSRegExp> boilerplate = Handle<JSRegExp>::cast(feedback);
+ FeedbackVectorRef feedback_vector(js_heap_broker(), p.feedback().vector());
+ ObjectRef feedback = feedback_vector.get(p.feedback().slot());
+ if (feedback.IsJSRegExp()) {
+ JSRegExpRef boilerplate = feedback.AsJSRegExp();
Node* value = effect = AllocateLiteralRegExp(effect, control, boilerplate);
ReplaceWithValue(node, value, effect, control);
return Replace(value);
@@ -1282,10 +1247,11 @@ Reduction JSCreateLowering::ReduceJSCreateLiteralRegExp(Node* node) {
}
Reduction JSCreateLowering::ReduceJSCreateFunctionContext(Node* node) {
+ DisallowHeapAccess no_heap_access;
DCHECK_EQ(IrOpcode::kJSCreateFunctionContext, node->opcode());
const CreateFunctionContextParameters& parameters =
CreateFunctionContextParametersOf(node->op());
- Handle<ScopeInfo> scope_info = parameters.scope_info();
+ ScopeInfoRef scope_info(js_heap_broker(), parameters.scope_info());
int slot_count = parameters.slot_count();
ScopeType scope_type = parameters.scope_type();
@@ -1329,8 +1295,9 @@ Reduction JSCreateLowering::ReduceJSCreateFunctionContext(Node* node) {
}
Reduction JSCreateLowering::ReduceJSCreateWithContext(Node* node) {
+ DisallowHeapAccess no_heap_access;
DCHECK_EQ(IrOpcode::kJSCreateWithContext, node->opcode());
- Handle<ScopeInfo> scope_info = ScopeInfoOf(node->op());
+ ScopeInfoRef scope_info(js_heap_broker(), ScopeInfoOf(node->op()));
Node* extension = NodeProperties::GetValueInput(node, 0);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
@@ -1350,8 +1317,9 @@ Reduction JSCreateLowering::ReduceJSCreateWithContext(Node* node) {
}
Reduction JSCreateLowering::ReduceJSCreateCatchContext(Node* node) {
+ DisallowHeapAccess no_heap_access;
DCHECK_EQ(IrOpcode::kJSCreateCatchContext, node->opcode());
- Handle<ScopeInfo> scope_info = ScopeInfoOf(node->op());
+ ScopeInfoRef scope_info(js_heap_broker(), ScopeInfoOf(node->op()));
Node* exception = NodeProperties::GetValueInput(node, 0);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
@@ -1375,9 +1343,10 @@ Reduction JSCreateLowering::ReduceJSCreateCatchContext(Node* node) {
}
Reduction JSCreateLowering::ReduceJSCreateBlockContext(Node* node) {
+ DisallowHeapAccess no_heap_access;
DCHECK_EQ(IrOpcode::kJSCreateBlockContext, node->opcode());
- Handle<ScopeInfo> scope_info = ScopeInfoOf(node->op());
- int const context_length = scope_info->ContextLength();
+ ScopeInfoRef scope_info(js_heap_broker(), ScopeInfoOf(node->op()));
+ int const context_length = scope_info.ContextLength();
// Use inline allocation for block contexts up to a size limit.
if (context_length < kBlockContextAllocationLimit) {
@@ -1408,22 +1377,24 @@ Reduction JSCreateLowering::ReduceJSCreateBlockContext(Node* node) {
}
Reduction JSCreateLowering::ReduceJSCreateObject(Node* node) {
+ DisallowHeapAccess no_heap_access;
DCHECK_EQ(IrOpcode::kJSCreateObject, node->opcode());
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* prototype = NodeProperties::GetValueInput(node, 0);
- HeapObjectMatcher m(prototype);
- if (!m.IsHeapConstant()) return NoChange();
-
- Handle<HeapObject> prototype_const = m.Value();
- Handle<Map> instance_map;
- MaybeHandle<Map> maybe_instance_map =
- Map::TryGetObjectCreateMap(prototype_const);
- if (!maybe_instance_map.ToHandle(&instance_map)) return NoChange();
+ Type prototype_type = NodeProperties::GetType(prototype);
+ if (!prototype_type.IsHeapConstant()) return NoChange();
+
+ HeapObjectRef prototype_const = prototype_type.AsHeapConstant()->Ref();
+ auto maybe_instance_map = prototype_const.TryGetObjectCreateMap();
+ if (!maybe_instance_map) return NoChange();
+ MapRef instance_map = maybe_instance_map.value();
+
Node* properties = jsgraph()->EmptyFixedArrayConstant();
- if (instance_map->is_dictionary_map()) {
- // Allocated an empty NameDictionary as backing store for the properties.
- Handle<Map> map(isolate()->heap()->name_dictionary_map(), isolate());
+ if (instance_map.is_dictionary_map()) {
+ DCHECK_EQ(prototype_const.type().oddball_type(), OddballType::kNull);
+ // Allocate an empty NameDictionary as backing store for the properties.
+ Handle<Map> map = isolate()->factory()->name_dictionary_map();
int capacity =
NameDictionary::ComputeCapacity(NameDictionary::kInitialCapacity);
DCHECK(base::bits::IsPowerOfTwo(capacity));
@@ -1460,9 +1431,9 @@ Reduction JSCreateLowering::ReduceJSCreateObject(Node* node) {
properties = effect = a.Finish();
}
- int const instance_size = instance_map->instance_size();
+ int const instance_size = instance_map.instance_size();
if (instance_size > kMaxRegularHeapObjectSize) return NoChange();
- dependencies()->AssumeInitialMapCantChange(instance_map);
+ CHECK(!instance_map.IsInobjectSlackTrackingInProgress());
// Emit code to allocate the JSObject instance for the given
// {instance_map}.
@@ -1543,14 +1514,14 @@ Node* JSCreateLowering::AllocateRestArguments(Node* effect, Node* control,
// given {context}. Serves as backing store for JSCreateArguments nodes.
Node* JSCreateLowering::AllocateAliasedArguments(
Node* effect, Node* control, Node* frame_state, Node* context,
- Handle<SharedFunctionInfo> shared, bool* has_aliased_arguments) {
+ const SharedFunctionInfoRef& shared, bool* has_aliased_arguments) {
FrameStateInfo state_info = FrameStateInfoOf(frame_state->op());
int argument_count = state_info.parameter_count() - 1; // Minus receiver.
if (argument_count == 0) return jsgraph()->EmptyFixedArrayConstant();
// If there is no aliasing, the arguments object elements are not special in
// any way, we can just return an unmapped backing store instead.
- int parameter_count = shared->internal_formal_parameter_count();
+ int parameter_count = shared.internal_formal_parameter_count();
if (parameter_count == 0) {
return AllocateArguments(effect, control, frame_state);
}
@@ -1596,11 +1567,11 @@ Node* JSCreateLowering::AllocateAliasedArguments(
// Serves as backing store for JSCreateArguments nodes.
Node* JSCreateLowering::AllocateAliasedArguments(
Node* effect, Node* control, Node* context, Node* arguments_frame,
- Node* arguments_length, Handle<SharedFunctionInfo> shared,
+ Node* arguments_length, const SharedFunctionInfoRef& shared,
bool* has_aliased_arguments) {
// If there is no aliasing, the arguments object elements are not
// special in any way, we can just return an unmapped backing store.
- int parameter_count = shared->internal_formal_parameter_count();
+ int parameter_count = shared.internal_formal_parameter_count();
if (parameter_count == 0) {
return graph()->NewNode(simplified()->NewArgumentsElements(0),
arguments_frame, arguments_length, effect);
@@ -1687,59 +1658,41 @@ Node* JSCreateLowering::AllocateElements(Node* effect, Node* control,
return a.Finish();
}
-Node* JSCreateLowering::AllocateFastLiteral(
- Node* effect, Node* control, Handle<JSObject> boilerplate,
- AllocationSiteUsageContext* site_context) {
- Handle<AllocationSite> current_site(*site_context->current(), isolate());
- dependencies()->AssumeTransitionStable(current_site);
-
- PretenureFlag pretenure = NOT_TENURED;
- if (FLAG_allocation_site_pretenuring) {
- Handle<AllocationSite> top_site(*site_context->top(), isolate());
- pretenure = top_site->GetPretenureMode();
- if (current_site.is_identical_to(top_site)) {
- // We install a dependency for pretenuring only on the outermost literal.
- dependencies()->AssumeTenuringDecision(top_site);
- }
- }
-
+Node* JSCreateLowering::AllocateFastLiteral(Node* effect, Node* control,
+ JSObjectRef boilerplate,
+ PretenureFlag pretenure) {
// Setup the properties backing store.
Node* properties = jsgraph()->EmptyFixedArrayConstant();
// Compute the in-object properties to store first (might have effects).
- Handle<Map> boilerplate_map(boilerplate->map(), isolate());
+ MapRef boilerplate_map = boilerplate.map();
ZoneVector<std::pair<FieldAccess, Node*>> inobject_fields(zone());
- inobject_fields.reserve(boilerplate_map->GetInObjectProperties());
- int const boilerplate_nof = boilerplate_map->NumberOfOwnDescriptors();
+ inobject_fields.reserve(boilerplate_map.GetInObjectProperties());
+ int const boilerplate_nof = boilerplate_map.NumberOfOwnDescriptors();
for (int i = 0; i < boilerplate_nof; ++i) {
PropertyDetails const property_details =
- boilerplate_map->instance_descriptors()->GetDetails(i);
+ boilerplate_map.GetPropertyDetails(i);
if (property_details.location() != kField) continue;
DCHECK_EQ(kData, property_details.kind());
- Handle<Name> property_name(
- boilerplate_map->instance_descriptors()->GetKey(i), isolate());
- FieldIndex index = FieldIndex::ForDescriptor(*boilerplate_map, i);
- FieldAccess access = {kTaggedBase, index.offset(),
- property_name, MaybeHandle<Map>(),
- Type::Any(), MachineType::AnyTagged(),
- kFullWriteBarrier};
+ NameRef property_name = boilerplate_map.GetPropertyKey(i);
+ FieldIndex index = boilerplate_map.GetFieldIndexFor(i);
+ FieldAccess access = {
+ kTaggedBase, index.offset(), property_name.object<Name>(),
+ MaybeHandle<Map>(), Type::Any(), MachineType::AnyTagged(),
+ kFullWriteBarrier};
Node* value;
- if (boilerplate->IsUnboxedDoubleField(index)) {
+ if (boilerplate.IsUnboxedDoubleField(index)) {
access.machine_type = MachineType::Float64();
access.type = Type::Number();
- value = jsgraph()->Constant(boilerplate->RawFastDoublePropertyAt(index));
+ value = jsgraph()->Constant(boilerplate.RawFastDoublePropertyAt(index));
} else {
- Handle<Object> boilerplate_value(boilerplate->RawFastPropertyAt(index),
- isolate());
- if (boilerplate_value->IsJSObject()) {
- Handle<JSObject> boilerplate_object =
- Handle<JSObject>::cast(boilerplate_value);
- Handle<AllocationSite> current_site = site_context->EnterNewScope();
- value = effect = AllocateFastLiteral(effect, control,
- boilerplate_object, site_context);
- site_context->ExitScope(current_site, boilerplate_object);
+ ObjectRef boilerplate_value = boilerplate.RawFastPropertyAt(index);
+ if (boilerplate_value.IsJSObject()) {
+ JSObjectRef boilerplate_object = boilerplate_value.AsJSObject();
+ value = effect =
+ AllocateFastLiteral(effect, control, boilerplate_object, pretenure);
} else if (property_details.representation().IsDouble()) {
- double number = Handle<HeapNumber>::cast(boilerplate_value)->value();
+ double number = boilerplate_value.AsMutableHeapNumber().value();
// Allocate a mutable HeapNumber box and store the value into it.
AllocationBuilder builder(jsgraph(), effect, control);
builder.Allocate(HeapNumber::kSize, pretenure);
@@ -1750,9 +1703,9 @@ Node* JSCreateLowering::AllocateFastLiteral(
value = effect = builder.Finish();
} else if (property_details.representation().IsSmi()) {
// Ensure that value is stored as smi.
- value = boilerplate_value->IsUninitialized(isolate())
+ value = boilerplate_value.oddball_type() == OddballType::kUninitialized
? jsgraph()->ZeroConstant()
- : jsgraph()->Constant(boilerplate_value);
+ : jsgraph()->Constant(boilerplate_value.AsSmi());
} else {
value = jsgraph()->Constant(boilerplate_value);
}
@@ -1761,7 +1714,7 @@ Node* JSCreateLowering::AllocateFastLiteral(
}
// Fill slack at the end of the boilerplate object with filler maps.
- int const boilerplate_length = boilerplate_map->GetInObjectProperties();
+ int const boilerplate_length = boilerplate_map.GetInObjectProperties();
for (int index = static_cast<int>(inobject_fields.size());
index < boilerplate_length; ++index) {
FieldAccess access =
@@ -1771,22 +1724,22 @@ Node* JSCreateLowering::AllocateFastLiteral(
}
// Setup the elements backing store.
- Node* elements = AllocateFastLiteralElements(effect, control, boilerplate,
- pretenure, site_context);
+ Node* elements =
+ AllocateFastLiteralElements(effect, control, boilerplate, pretenure);
if (elements->op()->EffectOutputCount() > 0) effect = elements;
// Actually allocate and initialize the object.
AllocationBuilder builder(jsgraph(), effect, control);
- builder.Allocate(boilerplate_map->instance_size(), pretenure,
- Type::For(boilerplate_map));
+ builder.Allocate(boilerplate_map.instance_size(), pretenure,
+ Type::For(js_heap_broker(), boilerplate_map.object<Map>()));
builder.Store(AccessBuilder::ForMap(), boilerplate_map);
builder.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
builder.Store(AccessBuilder::ForJSObjectElements(), elements);
- if (boilerplate_map->IsJSArrayMap()) {
- Handle<JSArray> boilerplate_array = Handle<JSArray>::cast(boilerplate);
+ if (boilerplate_map.IsJSArrayMap()) {
+ JSArrayRef boilerplate_array = boilerplate.AsJSArray();
builder.Store(
- AccessBuilder::ForJSArrayLength(boilerplate_array->GetElementsKind()),
- handle(boilerplate_array->length(), isolate()));
+ AccessBuilder::ForJSArrayLength(boilerplate_array.GetElementsKind()),
+ boilerplate_array.length());
}
for (auto const& inobject_field : inobject_fields) {
builder.Store(inobject_field.first, inobject_field.second);
@@ -1794,57 +1747,43 @@ Node* JSCreateLowering::AllocateFastLiteral(
return builder.Finish();
}
-Node* JSCreateLowering::AllocateFastLiteralElements(
- Node* effect, Node* control, Handle<JSObject> boilerplate,
- PretenureFlag pretenure, AllocationSiteUsageContext* site_context) {
- Handle<FixedArrayBase> boilerplate_elements(boilerplate->elements(),
- isolate());
+Node* JSCreateLowering::AllocateFastLiteralElements(Node* effect, Node* control,
+ JSObjectRef boilerplate,
+ PretenureFlag pretenure) {
+ FixedArrayBaseRef boilerplate_elements = boilerplate.elements();
// Empty or copy-on-write elements just store a constant.
- if (boilerplate_elements->length() == 0 ||
- boilerplate_elements->map() == isolate()->heap()->fixed_cow_array_map()) {
- if (pretenure == TENURED &&
- isolate()->heap()->InNewSpace(*boilerplate_elements)) {
- // If we would like to pretenure a fixed cow array, we must ensure that
- // the array is already in old space, otherwise we'll create too many
- // old-to-new-space pointers (overflowing the store buffer).
- boilerplate_elements = Handle<FixedArrayBase>(
- isolate()->factory()->CopyAndTenureFixedCOWArray(
- Handle<FixedArray>::cast(boilerplate_elements)));
- boilerplate->set_elements(*boilerplate_elements);
+ int const elements_length = boilerplate_elements.length();
+ MapRef elements_map = boilerplate_elements.map();
+ if (boilerplate_elements.length() == 0 || elements_map.IsFixedCowArrayMap()) {
+ if (pretenure == TENURED) {
+ boilerplate.EnsureElementsTenured();
+ boilerplate_elements = boilerplate.elements();
}
- return jsgraph()->HeapConstant(boilerplate_elements);
+ return jsgraph()->HeapConstant(boilerplate_elements.object<HeapObject>());
}
// Compute the elements to store first (might have effects).
- int const elements_length = boilerplate_elements->length();
- Handle<Map> elements_map(boilerplate_elements->map(), isolate());
ZoneVector<Node*> elements_values(elements_length, zone());
- if (elements_map->instance_type() == FIXED_DOUBLE_ARRAY_TYPE) {
- Handle<FixedDoubleArray> elements =
- Handle<FixedDoubleArray>::cast(boilerplate_elements);
+ if (elements_map.instance_type() == FIXED_DOUBLE_ARRAY_TYPE) {
+ FixedDoubleArrayRef elements = boilerplate_elements.AsFixedDoubleArray();
for (int i = 0; i < elements_length; ++i) {
- if (elements->is_the_hole(i)) {
+ if (elements.is_the_hole(i)) {
elements_values[i] = jsgraph()->TheHoleConstant();
} else {
- elements_values[i] = jsgraph()->Constant(elements->get_scalar(i));
+ elements_values[i] = jsgraph()->Constant(elements.get_scalar(i));
}
}
} else {
- Handle<FixedArray> elements =
- Handle<FixedArray>::cast(boilerplate_elements);
+ FixedArrayRef elements = boilerplate_elements.AsFixedArray();
for (int i = 0; i < elements_length; ++i) {
- if (elements->is_the_hole(isolate(), i)) {
+ if (elements.is_the_hole(i)) {
elements_values[i] = jsgraph()->TheHoleConstant();
} else {
- Handle<Object> element_value(elements->get(i), isolate());
- if (element_value->IsJSObject()) {
- Handle<JSObject> boilerplate_object =
- Handle<JSObject>::cast(element_value);
- Handle<AllocationSite> current_site = site_context->EnterNewScope();
+ ObjectRef element_value = elements.get(i);
+ if (element_value.IsJSObject()) {
elements_values[i] = effect = AllocateFastLiteral(
- effect, control, boilerplate_object, site_context);
- site_context->ExitScope(current_site, boilerplate_object);
+ effect, control, element_value.AsJSObject(), pretenure);
} else {
elements_values[i] = jsgraph()->Constant(element_value);
}
@@ -1854,9 +1793,9 @@ Node* JSCreateLowering::AllocateFastLiteralElements(
// Allocate the backing store array and store the elements.
AllocationBuilder builder(jsgraph(), effect, control);
- builder.AllocateArray(elements_length, elements_map, pretenure);
+ builder.AllocateArray(elements_length, elements_map.object<Map>(), pretenure);
ElementAccess const access =
- (elements_map->instance_type() == FIXED_DOUBLE_ARRAY_TYPE)
+ (elements_map.instance_type() == FIXED_DOUBLE_ARRAY_TYPE)
? AccessBuilder::ForFixedDoubleArrayElement()
: AccessBuilder::ForFixedArrayElement();
for (int i = 0; i < elements_length; ++i) {
@@ -1866,8 +1805,8 @@ Node* JSCreateLowering::AllocateFastLiteralElements(
}
Node* JSCreateLowering::AllocateLiteralRegExp(Node* effect, Node* control,
- Handle<JSRegExp> boilerplate) {
- Handle<Map> boilerplate_map(boilerplate->map(), isolate());
+ JSRegExpRef boilerplate) {
+ MapRef boilerplate_map = boilerplate.map();
// Sanity check that JSRegExp object layout hasn't changed.
STATIC_ASSERT(JSRegExp::kDataOffset == JSObject::kHeaderSize);
@@ -1884,21 +1823,18 @@ Node* JSCreateLowering::AllocateLiteralRegExp(Node* effect, Node* control,
JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
AllocationBuilder builder(jsgraph(), effect, control);
- builder.Allocate(size, pretenure, Type::For(boilerplate_map));
+ builder.Allocate(size, pretenure,
+ Type::For(js_heap_broker(), boilerplate_map.object<Map>()));
builder.Store(AccessBuilder::ForMap(), boilerplate_map);
builder.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
- handle(boilerplate->raw_properties_or_hash(), isolate()));
- builder.Store(AccessBuilder::ForJSObjectElements(),
- handle(boilerplate->elements(), isolate()));
-
- builder.Store(AccessBuilder::ForJSRegExpData(),
- handle(boilerplate->data(), isolate()));
- builder.Store(AccessBuilder::ForJSRegExpSource(),
- handle(boilerplate->source(), isolate()));
- builder.Store(AccessBuilder::ForJSRegExpFlags(),
- handle(boilerplate->flags(), isolate()));
+ boilerplate.raw_properties_or_hash());
+ builder.Store(AccessBuilder::ForJSObjectElements(), boilerplate.elements());
+
+ builder.Store(AccessBuilder::ForJSRegExpData(), boilerplate.data());
+ builder.Store(AccessBuilder::ForJSRegExpSource(), boilerplate.source());
+ builder.Store(AccessBuilder::ForJSRegExpFlags(), boilerplate.flags());
builder.Store(AccessBuilder::ForJSRegExpLastIndex(),
- handle(boilerplate->last_index(), isolate()));
+ boilerplate.last_index());
return builder.Finish();
}
@@ -1917,6 +1853,10 @@ SimplifiedOperatorBuilder* JSCreateLowering::simplified() const {
return jsgraph()->simplified();
}
+NativeContextRef JSCreateLowering::native_context_ref() const {
+ return NativeContextRef(js_heap_broker(), native_context());
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8