diff options
Diffstat (limited to 'deps/v8/src/compiler/js-create-lowering.cc')
-rw-r--r-- | deps/v8/src/compiler/js-create-lowering.cc | 690 |
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 |