• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/compiler/js-create-lowering.h"
6 
7 #include "src/code-factory.h"
8 #include "src/compiler/access-builder.h"
9 #include "src/compiler/allocation-builder.h"
10 #include "src/compiler/common-operator.h"
11 #include "src/compiler/compilation-dependencies.h"
12 #include "src/compiler/js-graph.h"
13 #include "src/compiler/js-operator.h"
14 #include "src/compiler/linkage.h"
15 #include "src/compiler/node-matchers.h"
16 #include "src/compiler/node-properties.h"
17 #include "src/compiler/node.h"
18 #include "src/compiler/operator-properties.h"
19 #include "src/compiler/simplified-operator.h"
20 #include "src/compiler/state-values-utils.h"
21 #include "src/objects-inl.h"
22 #include "src/objects/arguments.h"
23 #include "src/objects/hash-table-inl.h"
24 #include "src/objects/js-generator.h"
25 #include "src/objects/js-promise.h"
26 #include "src/objects/js-regexp-inl.h"
27 
28 namespace v8 {
29 namespace internal {
30 namespace compiler {
31 
32 namespace {
33 
34 // Retrieves the frame state holding actual argument values.
GetArgumentsFrameState(Node * frame_state)35 Node* GetArgumentsFrameState(Node* frame_state) {
36   Node* const outer_state = NodeProperties::GetFrameStateInput(frame_state);
37   FrameStateInfo outer_state_info = FrameStateInfoOf(outer_state->op());
38   return outer_state_info.type() == FrameStateType::kArgumentsAdaptor
39              ? outer_state
40              : frame_state;
41 }
42 
43 // Checks whether allocation using the given target and new.target can be
44 // inlined.
IsAllocationInlineable(const JSFunctionRef & target,const JSFunctionRef & new_target)45 bool IsAllocationInlineable(const JSFunctionRef& target,
46                             const JSFunctionRef& new_target) {
47   CHECK_IMPLIES(new_target.has_initial_map(),
48                 !new_target.initial_map().is_dictionary_map());
49   return new_target.has_initial_map() &&
50          new_target.initial_map().constructor_or_backpointer().equals(target);
51 }
52 
53 // When initializing arrays, we'll unfold the loop if the number of
54 // elements is known to be of this type.
55 const int kElementLoopUnrollLimit = 16;
56 
57 // Limits up to which context allocations are inlined.
58 const int kFunctionContextAllocationLimit = 16;
59 const int kBlockContextAllocationLimit = 16;
60 
61 }  // namespace
62 
Reduce(Node * node)63 Reduction JSCreateLowering::Reduce(Node* node) {
64   DisallowHeapAccess disallow_heap_access;
65   switch (node->opcode()) {
66     case IrOpcode::kJSCreate:
67       return ReduceJSCreate(node);
68     case IrOpcode::kJSCreateArguments:
69       return ReduceJSCreateArguments(node);
70     case IrOpcode::kJSCreateArray:
71       return ReduceJSCreateArray(node);
72     case IrOpcode::kJSCreateArrayIterator:
73       return ReduceJSCreateArrayIterator(node);
74     case IrOpcode::kJSCreateBoundFunction:
75       return ReduceJSCreateBoundFunction(node);
76     case IrOpcode::kJSCreateClosure:
77       return ReduceJSCreateClosure(node);
78     case IrOpcode::kJSCreateCollectionIterator:
79       return ReduceJSCreateCollectionIterator(node);
80     case IrOpcode::kJSCreateIterResultObject:
81       return ReduceJSCreateIterResultObject(node);
82     case IrOpcode::kJSCreateStringIterator:
83       return ReduceJSCreateStringIterator(node);
84     case IrOpcode::kJSCreateKeyValueArray:
85       return ReduceJSCreateKeyValueArray(node);
86     case IrOpcode::kJSCreatePromise:
87       return ReduceJSCreatePromise(node);
88     case IrOpcode::kJSCreateLiteralArray:
89     case IrOpcode::kJSCreateLiteralObject:
90       return ReduceJSCreateLiteralArrayOrObject(node);
91     case IrOpcode::kJSCreateLiteralRegExp:
92       return ReduceJSCreateLiteralRegExp(node);
93     case IrOpcode::kJSCreateEmptyLiteralArray:
94       return ReduceJSCreateEmptyLiteralArray(node);
95     case IrOpcode::kJSCreateEmptyLiteralObject:
96       return ReduceJSCreateEmptyLiteralObject(node);
97     case IrOpcode::kJSCreateFunctionContext:
98       return ReduceJSCreateFunctionContext(node);
99     case IrOpcode::kJSCreateWithContext:
100       return ReduceJSCreateWithContext(node);
101     case IrOpcode::kJSCreateCatchContext:
102       return ReduceJSCreateCatchContext(node);
103     case IrOpcode::kJSCreateBlockContext:
104       return ReduceJSCreateBlockContext(node);
105     case IrOpcode::kJSCreateGeneratorObject:
106       return ReduceJSCreateGeneratorObject(node);
107     case IrOpcode::kJSCreateObject:
108       return ReduceJSCreateObject(node);
109     default:
110       break;
111   }
112   return NoChange();
113 }
114 
ReduceJSCreate(Node * node)115 Reduction JSCreateLowering::ReduceJSCreate(Node* node) {
116   DCHECK_EQ(IrOpcode::kJSCreate, node->opcode());
117   Node* const target = NodeProperties::GetValueInput(node, 0);
118   Type const target_type = NodeProperties::GetType(target);
119   Node* const new_target = NodeProperties::GetValueInput(node, 1);
120   Type const new_target_type = NodeProperties::GetType(new_target);
121   Node* const effect = NodeProperties::GetEffectInput(node);
122   Node* const control = NodeProperties::GetControlInput(node);
123   // Extract constructor and original constructor function.
124   if (!target_type.IsHeapConstant() || !new_target_type.IsHeapConstant() ||
125       !target_type.AsHeapConstant()->Ref().IsJSFunction() ||
126       !new_target_type.AsHeapConstant()->Ref().IsJSFunction()) {
127     return NoChange();
128   }
129 
130   JSFunctionRef constructor =
131       target_type.AsHeapConstant()->Ref().AsJSFunction();
132   if (!constructor.IsConstructor()) return NoChange();
133   JSFunctionRef original_constructor =
134       new_target_type.AsHeapConstant()->Ref().AsJSFunction();
135   if (!original_constructor.IsConstructor()) return NoChange();
136 
137   // Check if we can inline the allocation.
138   if (!IsAllocationInlineable(constructor, original_constructor)) {
139     return NoChange();
140   }
141 
142   SlackTrackingPrediction slack_tracking_prediction =
143       dependencies()->DependOnInitialMapInstanceSizePrediction(
144           original_constructor);
145   MapRef initial_map = original_constructor.initial_map();
146 
147   // Emit code to allocate the JSObject instance for the
148   // {original_constructor}.
149   AllocationBuilder a(jsgraph(), effect, control);
150   a.Allocate(slack_tracking_prediction.instance_size());
151   a.Store(AccessBuilder::ForMap(), initial_map);
152   a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
153           jsgraph()->EmptyFixedArrayConstant());
154   a.Store(AccessBuilder::ForJSObjectElements(),
155           jsgraph()->EmptyFixedArrayConstant());
156   for (int i = 0; i < slack_tracking_prediction.inobject_property_count();
157        ++i) {
158     a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
159             jsgraph()->UndefinedConstant());
160   }
161 
162   RelaxControls(node);
163   a.FinishAndChange(node);
164   return Changed(node);
165 }
166 
ReduceJSCreateArguments(Node * node)167 Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
168   DCHECK_EQ(IrOpcode::kJSCreateArguments, node->opcode());
169   CreateArgumentsType type = CreateArgumentsTypeOf(node->op());
170   Node* const frame_state = NodeProperties::GetFrameStateInput(node);
171   Node* const outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
172   Node* const control = graph()->start();
173   FrameStateInfo state_info = FrameStateInfoOf(frame_state->op());
174   SharedFunctionInfoRef shared(js_heap_broker(),
175                                state_info.shared_info().ToHandleChecked());
176 
177   // Use the ArgumentsAccessStub for materializing both mapped and unmapped
178   // arguments object, but only for non-inlined (i.e. outermost) frames.
179   if (outer_state->opcode() != IrOpcode::kFrameState) {
180     switch (type) {
181       case CreateArgumentsType::kMappedArguments: {
182         // TODO(mstarzinger): Duplicate parameters are not handled yet.
183         if (shared.has_duplicate_parameters()) return NoChange();
184         Node* const callee = NodeProperties::GetValueInput(node, 0);
185         Node* const context = NodeProperties::GetContextInput(node);
186         Node* effect = NodeProperties::GetEffectInput(node);
187         Node* const arguments_frame =
188             graph()->NewNode(simplified()->ArgumentsFrame());
189         Node* const arguments_length = graph()->NewNode(
190             simplified()->ArgumentsLength(
191                 shared.internal_formal_parameter_count(), false),
192             arguments_frame);
193         // Allocate the elements backing store.
194         bool has_aliased_arguments = false;
195         Node* const elements = effect = AllocateAliasedArguments(
196             effect, control, context, arguments_frame, arguments_length, shared,
197             &has_aliased_arguments);
198         // Load the arguments object map.
199         Node* const arguments_map = jsgraph()->Constant(
200             has_aliased_arguments
201                 ? native_context_ref().fast_aliased_arguments_map()
202                 : native_context_ref().sloppy_arguments_map());
203         // Actually allocate and initialize the arguments object.
204         AllocationBuilder a(jsgraph(), effect, control);
205         Node* properties = jsgraph()->EmptyFixedArrayConstant();
206         STATIC_ASSERT(JSSloppyArgumentsObject::kSize == 5 * kPointerSize);
207         a.Allocate(JSSloppyArgumentsObject::kSize);
208         a.Store(AccessBuilder::ForMap(), arguments_map);
209         a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
210         a.Store(AccessBuilder::ForJSObjectElements(), elements);
211         a.Store(AccessBuilder::ForArgumentsLength(), arguments_length);
212         a.Store(AccessBuilder::ForArgumentsCallee(), callee);
213         RelaxControls(node);
214         a.FinishAndChange(node);
215         return Changed(node);
216       }
217       case CreateArgumentsType::kUnmappedArguments: {
218         Node* effect = NodeProperties::GetEffectInput(node);
219         Node* const arguments_frame =
220             graph()->NewNode(simplified()->ArgumentsFrame());
221         Node* const arguments_length = graph()->NewNode(
222             simplified()->ArgumentsLength(
223                 shared.internal_formal_parameter_count(), false),
224             arguments_frame);
225         // Allocate the elements backing store.
226         Node* const elements = effect =
227             graph()->NewNode(simplified()->NewArgumentsElements(0),
228                              arguments_frame, arguments_length, effect);
229         // Load the arguments object map.
230         Node* const arguments_map =
231             jsgraph()->Constant(native_context_ref().strict_arguments_map());
232         // Actually allocate and initialize the arguments object.
233         AllocationBuilder a(jsgraph(), effect, control);
234         Node* properties = jsgraph()->EmptyFixedArrayConstant();
235         STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize);
236         a.Allocate(JSStrictArgumentsObject::kSize);
237         a.Store(AccessBuilder::ForMap(), arguments_map);
238         a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
239         a.Store(AccessBuilder::ForJSObjectElements(), elements);
240         a.Store(AccessBuilder::ForArgumentsLength(), arguments_length);
241         RelaxControls(node);
242         a.FinishAndChange(node);
243         return Changed(node);
244       }
245       case CreateArgumentsType::kRestParameter: {
246         Node* effect = NodeProperties::GetEffectInput(node);
247         Node* const arguments_frame =
248             graph()->NewNode(simplified()->ArgumentsFrame());
249         Node* const rest_length = graph()->NewNode(
250             simplified()->ArgumentsLength(
251                 shared.internal_formal_parameter_count(), true),
252             arguments_frame);
253         // Allocate the elements backing store. Since NewArgumentsElements
254         // copies from the end of the arguments adapter frame, this is a suffix
255         // of the actual arguments.
256         Node* const elements = effect =
257             graph()->NewNode(simplified()->NewArgumentsElements(0),
258                              arguments_frame, rest_length, effect);
259         // Load the JSArray object map.
260         Node* const jsarray_map = jsgraph()->Constant(
261             native_context_ref().js_array_packed_elements_map());
262         // Actually allocate and initialize the jsarray.
263         AllocationBuilder a(jsgraph(), effect, control);
264         Node* properties = jsgraph()->EmptyFixedArrayConstant();
265         STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize);
266         a.Allocate(JSArray::kSize);
267         a.Store(AccessBuilder::ForMap(), jsarray_map);
268         a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
269         a.Store(AccessBuilder::ForJSObjectElements(), elements);
270         a.Store(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS), rest_length);
271         RelaxControls(node);
272         a.FinishAndChange(node);
273         return Changed(node);
274       }
275     }
276     UNREACHABLE();
277   } else if (outer_state->opcode() == IrOpcode::kFrameState) {
278     // Use inline allocation for all mapped arguments objects within inlined
279     // (i.e. non-outermost) frames, independent of the object size.
280     if (type == CreateArgumentsType::kMappedArguments) {
281       Node* const callee = NodeProperties::GetValueInput(node, 0);
282       Node* const context = NodeProperties::GetContextInput(node);
283       Node* effect = NodeProperties::GetEffectInput(node);
284       // TODO(mstarzinger): Duplicate parameters are not handled yet.
285       if (shared.has_duplicate_parameters()) return NoChange();
286       // Choose the correct frame state and frame state info depending on
287       // whether there conceptually is an arguments adaptor frame in the call
288       // chain.
289       Node* const args_state = GetArgumentsFrameState(frame_state);
290       if (args_state->InputAt(kFrameStateParametersInput)->opcode() ==
291           IrOpcode::kDeadValue) {
292         // This protects against an incompletely propagated DeadValue node.
293         // If the FrameState has a DeadValue input, then this node will be
294         // pruned anyway.
295         return NoChange();
296       }
297       FrameStateInfo args_state_info = FrameStateInfoOf(args_state->op());
298       // Prepare element backing store to be used by arguments object.
299       bool has_aliased_arguments = false;
300       Node* const elements = AllocateAliasedArguments(
301           effect, control, args_state, context, shared, &has_aliased_arguments);
302       effect = elements->op()->EffectOutputCount() > 0 ? elements : effect;
303       // Load the arguments object map.
304       Node* const arguments_map = jsgraph()->Constant(
305           has_aliased_arguments
306               ? native_context_ref().fast_aliased_arguments_map()
307               : native_context_ref().sloppy_arguments_map());
308       // Actually allocate and initialize the arguments object.
309       AllocationBuilder a(jsgraph(), effect, control);
310       Node* properties = jsgraph()->EmptyFixedArrayConstant();
311       int length = args_state_info.parameter_count() - 1;  // Minus receiver.
312       STATIC_ASSERT(JSSloppyArgumentsObject::kSize == 5 * kPointerSize);
313       a.Allocate(JSSloppyArgumentsObject::kSize);
314       a.Store(AccessBuilder::ForMap(), arguments_map);
315       a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
316       a.Store(AccessBuilder::ForJSObjectElements(), elements);
317       a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length));
318       a.Store(AccessBuilder::ForArgumentsCallee(), callee);
319       RelaxControls(node);
320       a.FinishAndChange(node);
321       return Changed(node);
322     } else if (type == CreateArgumentsType::kUnmappedArguments) {
323       // Use inline allocation for all unmapped arguments objects within inlined
324       // (i.e. non-outermost) frames, independent of the object size.
325       Node* effect = NodeProperties::GetEffectInput(node);
326       // Choose the correct frame state and frame state info depending on
327       // whether there conceptually is an arguments adaptor frame in the call
328       // chain.
329       Node* const args_state = GetArgumentsFrameState(frame_state);
330       if (args_state->InputAt(kFrameStateParametersInput)->opcode() ==
331           IrOpcode::kDeadValue) {
332         // This protects against an incompletely propagated DeadValue node.
333         // If the FrameState has a DeadValue input, then this node will be
334         // pruned anyway.
335         return NoChange();
336       }
337       FrameStateInfo args_state_info = FrameStateInfoOf(args_state->op());
338       // Prepare element backing store to be used by arguments object.
339       Node* const elements = AllocateArguments(effect, control, args_state);
340       effect = elements->op()->EffectOutputCount() > 0 ? elements : effect;
341       // Load the arguments object map.
342       Node* const arguments_map =
343           jsgraph()->Constant(native_context_ref().strict_arguments_map());
344       // Actually allocate and initialize the arguments object.
345       AllocationBuilder a(jsgraph(), effect, control);
346       Node* properties = jsgraph()->EmptyFixedArrayConstant();
347       int length = args_state_info.parameter_count() - 1;  // Minus receiver.
348       STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize);
349       a.Allocate(JSStrictArgumentsObject::kSize);
350       a.Store(AccessBuilder::ForMap(), arguments_map);
351       a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
352       a.Store(AccessBuilder::ForJSObjectElements(), elements);
353       a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length));
354       RelaxControls(node);
355       a.FinishAndChange(node);
356       return Changed(node);
357     } else if (type == CreateArgumentsType::kRestParameter) {
358       int start_index = shared.internal_formal_parameter_count();
359       // Use inline allocation for all unmapped arguments objects within inlined
360       // (i.e. non-outermost) frames, independent of the object size.
361       Node* effect = NodeProperties::GetEffectInput(node);
362       // Choose the correct frame state and frame state info depending on
363       // whether there conceptually is an arguments adaptor frame in the call
364       // chain.
365       Node* const args_state = GetArgumentsFrameState(frame_state);
366       if (args_state->InputAt(kFrameStateParametersInput)->opcode() ==
367           IrOpcode::kDeadValue) {
368         // This protects against an incompletely propagated DeadValue node.
369         // If the FrameState has a DeadValue input, then this node will be
370         // pruned anyway.
371         return NoChange();
372       }
373       FrameStateInfo args_state_info = FrameStateInfoOf(args_state->op());
374       // Prepare element backing store to be used by the rest array.
375       Node* const elements =
376           AllocateRestArguments(effect, control, args_state, start_index);
377       effect = elements->op()->EffectOutputCount() > 0 ? elements : effect;
378       // Load the JSArray object map.
379       Node* const jsarray_map = jsgraph()->Constant(
380           native_context_ref().js_array_packed_elements_map());
381       // Actually allocate and initialize the jsarray.
382       AllocationBuilder a(jsgraph(), effect, control);
383       Node* properties = jsgraph()->EmptyFixedArrayConstant();
384 
385       // -1 to minus receiver
386       int argument_count = args_state_info.parameter_count() - 1;
387       int length = std::max(0, argument_count - start_index);
388       STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize);
389       a.Allocate(JSArray::kSize);
390       a.Store(AccessBuilder::ForMap(), jsarray_map);
391       a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
392       a.Store(AccessBuilder::ForJSObjectElements(), elements);
393       a.Store(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS),
394               jsgraph()->Constant(length));
395       RelaxControls(node);
396       a.FinishAndChange(node);
397       return Changed(node);
398     }
399   }
400 
401   return NoChange();
402 }
403 
ReduceJSCreateGeneratorObject(Node * node)404 Reduction JSCreateLowering::ReduceJSCreateGeneratorObject(Node* node) {
405   DCHECK_EQ(IrOpcode::kJSCreateGeneratorObject, node->opcode());
406   Node* const closure = NodeProperties::GetValueInput(node, 0);
407   Node* const receiver = NodeProperties::GetValueInput(node, 1);
408   Node* const context = NodeProperties::GetContextInput(node);
409   Type const closure_type = NodeProperties::GetType(closure);
410   Node* effect = NodeProperties::GetEffectInput(node);
411   Node* const control = NodeProperties::GetControlInput(node);
412   if (closure_type.IsHeapConstant()) {
413     DCHECK(closure_type.AsHeapConstant()->Ref().IsJSFunction());
414     JSFunctionRef js_function =
415         closure_type.AsHeapConstant()->Ref().AsJSFunction();
416     if (!js_function.has_initial_map()) return NoChange();
417 
418     SlackTrackingPrediction slack_tracking_prediction =
419         dependencies()->DependOnInitialMapInstanceSizePrediction(js_function);
420 
421     MapRef initial_map = js_function.initial_map();
422     DCHECK(initial_map.instance_type() == JS_GENERATOR_OBJECT_TYPE ||
423            initial_map.instance_type() == JS_ASYNC_GENERATOR_OBJECT_TYPE);
424 
425     // Allocate a register file.
426     SharedFunctionInfoRef shared = js_function.shared();
427     DCHECK(shared.HasBytecodeArray());
428     int parameter_count_no_receiver = shared.internal_formal_parameter_count();
429     int size = parameter_count_no_receiver +
430                shared.GetBytecodeArray().register_count();
431     AllocationBuilder ab(jsgraph(), effect, control);
432     ab.AllocateArray(size, factory()->fixed_array_map());
433     for (int i = 0; i < size; ++i) {
434       ab.Store(AccessBuilder::ForFixedArraySlot(i),
435                jsgraph()->UndefinedConstant());
436     }
437     Node* parameters_and_registers = effect = ab.Finish();
438 
439     // Emit code to allocate the JS[Async]GeneratorObject instance.
440     AllocationBuilder a(jsgraph(), effect, control);
441     a.Allocate(slack_tracking_prediction.instance_size());
442     Node* empty_fixed_array = jsgraph()->EmptyFixedArrayConstant();
443     Node* undefined = jsgraph()->UndefinedConstant();
444     a.Store(AccessBuilder::ForMap(), initial_map);
445     a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), empty_fixed_array);
446     a.Store(AccessBuilder::ForJSObjectElements(), empty_fixed_array);
447     a.Store(AccessBuilder::ForJSGeneratorObjectContext(), context);
448     a.Store(AccessBuilder::ForJSGeneratorObjectFunction(), closure);
449     a.Store(AccessBuilder::ForJSGeneratorObjectReceiver(), receiver);
450     a.Store(AccessBuilder::ForJSGeneratorObjectInputOrDebugPos(), undefined);
451     a.Store(AccessBuilder::ForJSGeneratorObjectResumeMode(),
452             jsgraph()->Constant(JSGeneratorObject::kNext));
453     a.Store(AccessBuilder::ForJSGeneratorObjectContinuation(),
454             jsgraph()->Constant(JSGeneratorObject::kGeneratorExecuting));
455     a.Store(AccessBuilder::ForJSGeneratorObjectParametersAndRegisters(),
456             parameters_and_registers);
457 
458     if (initial_map.instance_type() == JS_ASYNC_GENERATOR_OBJECT_TYPE) {
459       a.Store(AccessBuilder::ForJSAsyncGeneratorObjectQueue(), undefined);
460       a.Store(AccessBuilder::ForJSAsyncGeneratorObjectIsAwaiting(),
461               jsgraph()->ZeroConstant());
462     }
463 
464     // Handle in-object properties, too.
465     for (int i = 0; i < slack_tracking_prediction.inobject_property_count();
466          ++i) {
467       a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
468               undefined);
469     }
470     a.FinishAndChange(node);
471     return Changed(node);
472   }
473   return NoChange();
474 }
475 
476 // Constructs an array with a variable {length} when no upper bound
477 // is known for the capacity.
ReduceNewArray(Node * node,Node * length,MapRef initial_map,PretenureFlag pretenure,const SlackTrackingPrediction & slack_tracking_prediction)478 Reduction JSCreateLowering::ReduceNewArray(
479     Node* node, Node* length, MapRef initial_map, PretenureFlag pretenure,
480     const SlackTrackingPrediction& slack_tracking_prediction) {
481   DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
482   Node* effect = NodeProperties::GetEffectInput(node);
483   Node* control = NodeProperties::GetControlInput(node);
484 
485   // Constructing an Array via new Array(N) where N is an unsigned
486   // integer, always creates a holey backing store.
487   ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(
488       initial_map, initial_map.AsElementsKind(
489                        GetHoleyElementsKind(initial_map.elements_kind())));
490 
491   // Check that the {limit} is an unsigned integer in the valid range.
492   // This has to be kept in sync with src/runtime/runtime-array.cc,
493   // where this limit is protected.
494   length = effect = graph()->NewNode(
495       simplified()->CheckBounds(VectorSlotPair()), length,
496       jsgraph()->Constant(JSArray::kInitialMaxFastElementArray), effect,
497       control);
498 
499   // Construct elements and properties for the resulting JSArray.
500   Node* elements = effect =
501       graph()->NewNode(IsDoubleElementsKind(initial_map.elements_kind())
502                            ? simplified()->NewDoubleElements(pretenure)
503                            : simplified()->NewSmiOrObjectElements(pretenure),
504                        length, effect, control);
505   Node* properties = jsgraph()->EmptyFixedArrayConstant();
506 
507   // Perform the allocation of the actual JSArray object.
508   AllocationBuilder a(jsgraph(), effect, control);
509   a.Allocate(slack_tracking_prediction.instance_size(), pretenure);
510   a.Store(AccessBuilder::ForMap(), initial_map);
511   a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
512   a.Store(AccessBuilder::ForJSObjectElements(), elements);
513   a.Store(AccessBuilder::ForJSArrayLength(initial_map.elements_kind()), length);
514   for (int i = 0; i < slack_tracking_prediction.inobject_property_count();
515        ++i) {
516     a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
517             jsgraph()->UndefinedConstant());
518   }
519   RelaxControls(node);
520   a.FinishAndChange(node);
521   return Changed(node);
522 }
523 
524 // Constructs an array with a variable {length} when an actual
525 // upper bound is known for the {capacity}.
ReduceNewArray(Node * node,Node * length,int capacity,MapRef initial_map,PretenureFlag pretenure,const SlackTrackingPrediction & slack_tracking_prediction)526 Reduction JSCreateLowering::ReduceNewArray(
527     Node* node, Node* length, int capacity, MapRef initial_map,
528     PretenureFlag pretenure,
529     const SlackTrackingPrediction& slack_tracking_prediction) {
530   DCHECK(node->opcode() == IrOpcode::kJSCreateArray ||
531          node->opcode() == IrOpcode::kJSCreateEmptyLiteralArray);
532   Node* effect = NodeProperties::GetEffectInput(node);
533   Node* control = NodeProperties::GetControlInput(node);
534 
535   // Determine the appropriate elements kind.
536   ElementsKind elements_kind = initial_map.elements_kind();
537   if (NodeProperties::GetType(length).Max() > 0.0) {
538     elements_kind = GetHoleyElementsKind(elements_kind);
539     ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(
540         initial_map, initial_map.AsElementsKind(elements_kind));
541   }
542   DCHECK(IsFastElementsKind(elements_kind));
543 
544   // Setup elements and properties.
545   Node* elements;
546   if (capacity == 0) {
547     elements = jsgraph()->EmptyFixedArrayConstant();
548   } else {
549     elements = effect =
550         AllocateElements(effect, control, elements_kind, capacity, pretenure);
551   }
552   Node* properties = jsgraph()->EmptyFixedArrayConstant();
553 
554   // Perform the allocation of the actual JSArray object.
555   AllocationBuilder a(jsgraph(), effect, control);
556   a.Allocate(slack_tracking_prediction.instance_size(), pretenure);
557   a.Store(AccessBuilder::ForMap(), initial_map);
558   a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
559   a.Store(AccessBuilder::ForJSObjectElements(), elements);
560   a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length);
561   for (int i = 0; i < slack_tracking_prediction.inobject_property_count();
562        ++i) {
563     a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
564             jsgraph()->UndefinedConstant());
565   }
566   RelaxControls(node);
567   a.FinishAndChange(node);
568   return Changed(node);
569 }
570 
ReduceNewArray(Node * node,std::vector<Node * > values,MapRef initial_map,PretenureFlag pretenure,const SlackTrackingPrediction & slack_tracking_prediction)571 Reduction JSCreateLowering::ReduceNewArray(
572     Node* node, std::vector<Node*> values, MapRef initial_map,
573     PretenureFlag pretenure,
574     const SlackTrackingPrediction& slack_tracking_prediction) {
575   DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
576   Node* effect = NodeProperties::GetEffectInput(node);
577   Node* control = NodeProperties::GetControlInput(node);
578 
579   // Determine the appropriate elements kind.
580   ElementsKind elements_kind = initial_map.elements_kind();
581   DCHECK(IsFastElementsKind(elements_kind));
582 
583   // Check {values} based on the {elements_kind}. These checks are guarded
584   // by the {elements_kind} feedback on the {site}, so it's safe to just
585   // deoptimize in this case.
586   if (IsSmiElementsKind(elements_kind)) {
587     for (auto& value : values) {
588       if (!NodeProperties::GetType(value).Is(Type::SignedSmall())) {
589         value = effect = graph()->NewNode(
590             simplified()->CheckSmi(VectorSlotPair()), value, effect, control);
591       }
592     }
593   } else if (IsDoubleElementsKind(elements_kind)) {
594     for (auto& value : values) {
595       if (!NodeProperties::GetType(value).Is(Type::Number())) {
596         value = effect =
597             graph()->NewNode(simplified()->CheckNumber(VectorSlotPair()), value,
598                              effect, control);
599       }
600       // Make sure we do not store signaling NaNs into double arrays.
601       value = graph()->NewNode(simplified()->NumberSilenceNaN(), value);
602     }
603   }
604 
605   // Setup elements, properties and length.
606   Node* elements = effect =
607       AllocateElements(effect, control, elements_kind, values, pretenure);
608   Node* properties = jsgraph()->EmptyFixedArrayConstant();
609   Node* length = jsgraph()->Constant(static_cast<int>(values.size()));
610 
611   // Perform the allocation of the actual JSArray object.
612   AllocationBuilder a(jsgraph(), effect, control);
613   a.Allocate(slack_tracking_prediction.instance_size(), pretenure);
614   a.Store(AccessBuilder::ForMap(), initial_map);
615   a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
616   a.Store(AccessBuilder::ForJSObjectElements(), elements);
617   a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length);
618   for (int i = 0; i < slack_tracking_prediction.inobject_property_count();
619        ++i) {
620     a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
621             jsgraph()->UndefinedConstant());
622   }
623   RelaxControls(node);
624   a.FinishAndChange(node);
625   return Changed(node);
626 }
627 
ReduceNewArrayToStubCall(Node * node,base::Optional<AllocationSiteRef> site)628 Reduction JSCreateLowering::ReduceNewArrayToStubCall(
629     Node* node, base::Optional<AllocationSiteRef> site) {
630   CreateArrayParameters const& p = CreateArrayParametersOf(node->op());
631   int const arity = static_cast<int>(p.arity());
632   Node* target = NodeProperties::GetValueInput(node, 0);
633   Node* new_target = NodeProperties::GetValueInput(node, 1);
634   Type new_target_type = NodeProperties::GetType(new_target);
635   Node* type_info =
636       site ? jsgraph()->Constant(*site) : jsgraph()->UndefinedConstant();
637 
638   ElementsKind elements_kind =
639       site ? site->GetElementsKind() : GetInitialFastElementsKind();
640   AllocationSiteOverrideMode override_mode =
641       (!site || AllocationSite::ShouldTrack(elements_kind))
642           ? DISABLE_ALLOCATION_SITES
643           : DONT_OVERRIDE;
644 
645   // The Array constructor can only trigger an observable side-effect
646   // if the new.target may be a proxy.
647   Operator::Properties const properties =
648       (new_target != target || new_target_type.Maybe(Type::Proxy()))
649           ? Operator::kNoDeopt
650           : Operator::kNoDeopt | Operator::kNoWrite;
651 
652   if (arity == 0) {
653     Callable callable = CodeFactory::ArrayNoArgumentConstructor(
654         isolate(), elements_kind, override_mode);
655     auto call_descriptor = Linkage::GetStubCallDescriptor(
656         graph()->zone(), callable.descriptor(), arity + 1,
657         CallDescriptor::kNeedsFrameState, properties);
658     node->ReplaceInput(0, jsgraph()->HeapConstant(callable.code()));
659     node->InsertInput(graph()->zone(), 2, type_info);
660     node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(arity));
661     node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
662     NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
663   } else if (arity == 1) {
664     // Require elements kind to "go holey".
665     Callable callable = CodeFactory::ArraySingleArgumentConstructor(
666         isolate(), GetHoleyElementsKind(elements_kind), override_mode);
667     auto call_descriptor = Linkage::GetStubCallDescriptor(
668         graph()->zone(), callable.descriptor(), arity + 1,
669         CallDescriptor::kNeedsFrameState, properties);
670     node->ReplaceInput(0, jsgraph()->HeapConstant(callable.code()));
671     node->InsertInput(graph()->zone(), 2, type_info);
672     node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(arity));
673     node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
674     NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
675   } else {
676     DCHECK_GT(arity, 1);
677     Handle<Code> code = BUILTIN_CODE(isolate(), ArrayNArgumentsConstructor);
678     auto call_descriptor = Linkage::GetStubCallDescriptor(
679         graph()->zone(), ArrayNArgumentsConstructorDescriptor{}, arity + 1,
680         CallDescriptor::kNeedsFrameState);
681     node->ReplaceInput(0, jsgraph()->HeapConstant(code));
682     node->InsertInput(graph()->zone(), 2, type_info);
683     node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(arity));
684     node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
685     NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
686   }
687   return Changed(node);
688 }
689 
ReduceJSCreateArray(Node * node)690 Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
691   DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
692   CreateArrayParameters const& p = CreateArrayParametersOf(node->op());
693   int const arity = static_cast<int>(p.arity());
694   base::Optional<AllocationSiteRef> site_ref;
695   {
696     Handle<AllocationSite> site;
697     if (p.site().ToHandle(&site)) {
698       site_ref = AllocationSiteRef(js_heap_broker(), site);
699     }
700   }
701   PretenureFlag pretenure = NOT_TENURED;
702   JSFunctionRef constructor = native_context_ref().array_function();
703   Node* target = NodeProperties::GetValueInput(node, 0);
704   Node* new_target = NodeProperties::GetValueInput(node, 1);
705   Type new_target_type = (target == new_target)
706                              ? Type::HeapConstant(constructor, zone())
707                              : NodeProperties::GetType(new_target);
708 
709   // Extract original constructor function.
710   if (new_target_type.IsHeapConstant() &&
711       new_target_type.AsHeapConstant()->Ref().IsJSFunction()) {
712     JSFunctionRef original_constructor =
713         new_target_type.AsHeapConstant()->Ref().AsJSFunction();
714     DCHECK(constructor.IsConstructor());
715     DCHECK(original_constructor.IsConstructor());
716 
717     // Check if we can inline the allocation.
718     if (IsAllocationInlineable(constructor, original_constructor)) {
719       SlackTrackingPrediction slack_tracking_prediction =
720           dependencies()->DependOnInitialMapInstanceSizePrediction(
721               original_constructor);
722       MapRef initial_map = original_constructor.initial_map();
723 
724       // Tells whether we are protected by either the {site} or a
725       // protector cell to do certain speculative optimizations.
726       bool can_inline_call = false;
727 
728       // Check if we have a feedback {site} on the {node}.
729       if (site_ref) {
730         ElementsKind elements_kind = site_ref->GetElementsKind();
731         ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(
732             initial_map, initial_map.AsElementsKind(elements_kind));
733         can_inline_call = site_ref->CanInlineCall();
734         pretenure = dependencies()->DependOnPretenureMode(*site_ref);
735         dependencies()->DependOnElementsKind(*site_ref);
736       } else {
737         can_inline_call = isolate()->IsArrayConstructorIntact();
738       }
739 
740       if (arity == 0) {
741         Node* length = jsgraph()->ZeroConstant();
742         int capacity = JSArray::kPreallocatedArrayElements;
743         return ReduceNewArray(node, length, capacity, initial_map, pretenure,
744                               slack_tracking_prediction);
745       } else if (arity == 1) {
746         Node* length = NodeProperties::GetValueInput(node, 2);
747         Type length_type = NodeProperties::GetType(length);
748         if (!length_type.Maybe(Type::Number())) {
749           // Handle the single argument case, where we know that the value
750           // cannot be a valid Array length.
751           ElementsKind elements_kind = initial_map.elements_kind();
752           elements_kind = GetMoreGeneralElementsKind(
753               elements_kind, IsHoleyElementsKind(elements_kind)
754                                  ? HOLEY_ELEMENTS
755                                  : PACKED_ELEMENTS);
756           ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(
757               initial_map, initial_map.AsElementsKind(elements_kind));
758           return ReduceNewArray(node, std::vector<Node*>{length}, initial_map,
759                                 pretenure, slack_tracking_prediction);
760         }
761         if (length_type.Is(Type::SignedSmall()) && length_type.Min() >= 0 &&
762             length_type.Max() <= kElementLoopUnrollLimit &&
763             length_type.Min() == length_type.Max()) {
764           int capacity = static_cast<int>(length_type.Max());
765           return ReduceNewArray(node, length, capacity, initial_map, pretenure,
766                                 slack_tracking_prediction);
767         }
768         if (length_type.Maybe(Type::UnsignedSmall()) && can_inline_call) {
769           return ReduceNewArray(node, length, initial_map, pretenure,
770                                 slack_tracking_prediction);
771         }
772       } else if (arity <= JSArray::kInitialMaxFastElementArray) {
773         // Gather the values to store into the newly created array.
774         bool values_all_smis = true, values_all_numbers = true,
775              values_any_nonnumber = false;
776         std::vector<Node*> values;
777         values.reserve(p.arity());
778         for (int i = 0; i < arity; ++i) {
779           Node* value = NodeProperties::GetValueInput(node, 2 + i);
780           Type value_type = NodeProperties::GetType(value);
781           if (!value_type.Is(Type::SignedSmall())) {
782             values_all_smis = false;
783           }
784           if (!value_type.Is(Type::Number())) {
785             values_all_numbers = false;
786           }
787           if (!value_type.Maybe(Type::Number())) {
788             values_any_nonnumber = true;
789           }
790           values.push_back(value);
791         }
792 
793         // Try to figure out the ideal elements kind statically.
794         ElementsKind elements_kind = initial_map.elements_kind();
795         if (values_all_smis) {
796           // Smis can be stored with any elements kind.
797         } else if (values_all_numbers) {
798           elements_kind = GetMoreGeneralElementsKind(
799               elements_kind, IsHoleyElementsKind(elements_kind)
800                                  ? HOLEY_DOUBLE_ELEMENTS
801                                  : PACKED_DOUBLE_ELEMENTS);
802         } else if (values_any_nonnumber) {
803           elements_kind = GetMoreGeneralElementsKind(
804               elements_kind, IsHoleyElementsKind(elements_kind)
805                                  ? HOLEY_ELEMENTS
806                                  : PACKED_ELEMENTS);
807         } else if (!can_inline_call) {
808           // We have some crazy combination of types for the {values} where
809           // there's no clear decision on the elements kind statically. And
810           // we don't have a protection against deoptimization loops for the
811           // checks that are introduced in the call to ReduceNewArray, so
812           // we cannot inline this invocation of the Array constructor here.
813           return NoChange();
814         }
815         ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(
816             initial_map, initial_map.AsElementsKind(elements_kind));
817         return ReduceNewArray(node, values, initial_map, pretenure,
818                               slack_tracking_prediction);
819       }
820     }
821   }
822 
823   // TODO(bmeurer): Optimize the subclassing case.
824   if (target != new_target) return NoChange();
825 
826   return ReduceNewArrayToStubCall(node, site_ref);
827 }
828 
ReduceJSCreateArrayIterator(Node * node)829 Reduction JSCreateLowering::ReduceJSCreateArrayIterator(Node* node) {
830   DCHECK_EQ(IrOpcode::kJSCreateArrayIterator, node->opcode());
831   CreateArrayIteratorParameters const& p =
832       CreateArrayIteratorParametersOf(node->op());
833   Node* iterated_object = NodeProperties::GetValueInput(node, 0);
834   Node* effect = NodeProperties::GetEffectInput(node);
835   Node* control = NodeProperties::GetControlInput(node);
836 
837   // Create the JSArrayIterator result.
838   AllocationBuilder a(jsgraph(), effect, control);
839   a.Allocate(JSArrayIterator::kSize, NOT_TENURED, Type::OtherObject());
840   a.Store(AccessBuilder::ForMap(),
841           native_context_ref().initial_array_iterator_map());
842   a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
843           jsgraph()->EmptyFixedArrayConstant());
844   a.Store(AccessBuilder::ForJSObjectElements(),
845           jsgraph()->EmptyFixedArrayConstant());
846   a.Store(AccessBuilder::ForJSArrayIteratorIteratedObject(), iterated_object);
847   a.Store(AccessBuilder::ForJSArrayIteratorNextIndex(),
848           jsgraph()->ZeroConstant());
849   a.Store(AccessBuilder::ForJSArrayIteratorKind(),
850           jsgraph()->Constant(static_cast<int>(p.kind())));
851   RelaxControls(node);
852   a.FinishAndChange(node);
853   return Changed(node);
854 }
855 
856 namespace {
857 
MapForCollectionIterationKind(const NativeContextRef & native_context,CollectionKind collection_kind,IterationKind iteration_kind)858 MapRef MapForCollectionIterationKind(const NativeContextRef& native_context,
859                                      CollectionKind collection_kind,
860                                      IterationKind iteration_kind) {
861   switch (collection_kind) {
862     case CollectionKind::kSet:
863       switch (iteration_kind) {
864         case IterationKind::kKeys:
865           UNREACHABLE();
866         case IterationKind::kValues:
867           return native_context.set_value_iterator_map();
868         case IterationKind::kEntries:
869           return native_context.set_key_value_iterator_map();
870       }
871       break;
872     case CollectionKind::kMap:
873       switch (iteration_kind) {
874         case IterationKind::kKeys:
875           return native_context.map_key_iterator_map();
876         case IterationKind::kValues:
877           return native_context.map_value_iterator_map();
878         case IterationKind::kEntries:
879           return native_context.map_key_value_iterator_map();
880       }
881       break;
882   }
883   UNREACHABLE();
884 }
885 
886 }  // namespace
887 
ReduceJSCreateCollectionIterator(Node * node)888 Reduction JSCreateLowering::ReduceJSCreateCollectionIterator(Node* node) {
889   DCHECK_EQ(IrOpcode::kJSCreateCollectionIterator, node->opcode());
890   CreateCollectionIteratorParameters const& p =
891       CreateCollectionIteratorParametersOf(node->op());
892   Node* iterated_object = NodeProperties::GetValueInput(node, 0);
893   Node* effect = NodeProperties::GetEffectInput(node);
894   Node* control = NodeProperties::GetControlInput(node);
895 
896   // Load the OrderedHashTable from the {receiver}.
897   Node* table = effect = graph()->NewNode(
898       simplified()->LoadField(AccessBuilder::ForJSCollectionTable()),
899       iterated_object, effect, control);
900 
901   // Create the JSArrayIterator result.
902   AllocationBuilder a(jsgraph(), effect, control);
903   a.Allocate(JSCollectionIterator::kSize, NOT_TENURED, Type::OtherObject());
904   a.Store(AccessBuilder::ForMap(),
905           MapForCollectionIterationKind(
906               native_context_ref(), p.collection_kind(), p.iteration_kind()));
907   a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
908           jsgraph()->EmptyFixedArrayConstant());
909   a.Store(AccessBuilder::ForJSObjectElements(),
910           jsgraph()->EmptyFixedArrayConstant());
911   a.Store(AccessBuilder::ForJSCollectionIteratorTable(), table);
912   a.Store(AccessBuilder::ForJSCollectionIteratorIndex(),
913           jsgraph()->ZeroConstant());
914   RelaxControls(node);
915   a.FinishAndChange(node);
916   return Changed(node);
917 }
918 
ReduceJSCreateBoundFunction(Node * node)919 Reduction JSCreateLowering::ReduceJSCreateBoundFunction(Node* node) {
920   DCHECK_EQ(IrOpcode::kJSCreateBoundFunction, node->opcode());
921   CreateBoundFunctionParameters const& p =
922       CreateBoundFunctionParametersOf(node->op());
923   int const arity = static_cast<int>(p.arity());
924   MapRef const map(js_heap_broker(), p.map());
925   Node* bound_target_function = NodeProperties::GetValueInput(node, 0);
926   Node* bound_this = NodeProperties::GetValueInput(node, 1);
927   Node* effect = NodeProperties::GetEffectInput(node);
928   Node* control = NodeProperties::GetControlInput(node);
929 
930   // Create the [[BoundArguments]] for the result.
931   Node* bound_arguments = jsgraph()->EmptyFixedArrayConstant();
932   if (arity > 0) {
933     AllocationBuilder a(jsgraph(), effect, control);
934     a.AllocateArray(arity, factory()->fixed_array_map());
935     for (int i = 0; i < arity; ++i) {
936       a.Store(AccessBuilder::ForFixedArraySlot(i),
937               NodeProperties::GetValueInput(node, 2 + i));
938     }
939     bound_arguments = effect = a.Finish();
940   }
941 
942   // Create the JSBoundFunction result.
943   AllocationBuilder a(jsgraph(), effect, control);
944   a.Allocate(JSBoundFunction::kSize, NOT_TENURED, Type::BoundFunction());
945   a.Store(AccessBuilder::ForMap(), map);
946   a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
947           jsgraph()->EmptyFixedArrayConstant());
948   a.Store(AccessBuilder::ForJSObjectElements(),
949           jsgraph()->EmptyFixedArrayConstant());
950   a.Store(AccessBuilder::ForJSBoundFunctionBoundTargetFunction(),
951           bound_target_function);
952   a.Store(AccessBuilder::ForJSBoundFunctionBoundThis(), bound_this);
953   a.Store(AccessBuilder::ForJSBoundFunctionBoundArguments(), bound_arguments);
954   RelaxControls(node);
955   a.FinishAndChange(node);
956   return Changed(node);
957 }
958 
ReduceJSCreateClosure(Node * node)959 Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) {
960   DCHECK_EQ(IrOpcode::kJSCreateClosure, node->opcode());
961   CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
962   SharedFunctionInfoRef shared(js_heap_broker(), p.shared_info());
963   HeapObjectRef feedback_cell(js_heap_broker(), p.feedback_cell());
964   HeapObjectRef code(js_heap_broker(), p.code());
965   Node* effect = NodeProperties::GetEffectInput(node);
966   Node* control = NodeProperties::GetControlInput(node);
967   Node* context = NodeProperties::GetContextInput(node);
968 
969   // Use inline allocation of closures only for instantiation sites that have
970   // seen more than one instantiation, this simplifies the generated code and
971   // also serves as a heuristic of which allocation sites benefit from it.
972   if (!feedback_cell.map().equals(
973           MapRef(js_heap_broker(), factory()->many_closures_cell_map()))) {
974     return NoChange();
975   }
976 
977   MapRef function_map =
978       native_context_ref().GetFunctionMapFromIndex(shared.function_map_index());
979   DCHECK(!function_map.IsInobjectSlackTrackingInProgress());
980   DCHECK(!function_map.is_dictionary_map());
981 
982   // TODO(turbofan): We should use the pretenure flag from {p} here,
983   // but currently the heuristic in the parser works against us, as
984   // it marks closures like
985   //
986   //   args[l] = function(...) { ... }
987   //
988   // for old-space allocation, which doesn't always make sense. For
989   // example in case of the bluebird-parallel benchmark, where this
990   // is a core part of the *promisify* logic (see crbug.com/810132).
991   PretenureFlag pretenure = NOT_TENURED;
992 
993   // Emit code to allocate the JSFunction instance.
994   STATIC_ASSERT(JSFunction::kSizeWithoutPrototype == 7 * kPointerSize);
995   AllocationBuilder a(jsgraph(), effect, control);
996   a.Allocate(function_map.instance_size(), pretenure, Type::Function());
997   a.Store(AccessBuilder::ForMap(), function_map);
998   a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
999           jsgraph()->EmptyFixedArrayConstant());
1000   a.Store(AccessBuilder::ForJSObjectElements(),
1001           jsgraph()->EmptyFixedArrayConstant());
1002   a.Store(AccessBuilder::ForJSFunctionSharedFunctionInfo(), shared);
1003   a.Store(AccessBuilder::ForJSFunctionContext(), context);
1004   a.Store(AccessBuilder::ForJSFunctionFeedbackCell(), feedback_cell);
1005   a.Store(AccessBuilder::ForJSFunctionCode(), code);
1006   STATIC_ASSERT(JSFunction::kSizeWithoutPrototype == 7 * kPointerSize);
1007   if (function_map.has_prototype_slot()) {
1008     a.Store(AccessBuilder::ForJSFunctionPrototypeOrInitialMap(),
1009             jsgraph()->TheHoleConstant());
1010     STATIC_ASSERT(JSFunction::kSizeWithPrototype == 8 * kPointerSize);
1011   }
1012   for (int i = 0; i < function_map.GetInObjectProperties(); i++) {
1013     a.Store(AccessBuilder::ForJSObjectInObjectProperty(function_map, i),
1014             jsgraph()->UndefinedConstant());
1015   }
1016   RelaxControls(node);
1017   a.FinishAndChange(node);
1018   return Changed(node);
1019 }
1020 
ReduceJSCreateIterResultObject(Node * node)1021 Reduction JSCreateLowering::ReduceJSCreateIterResultObject(Node* node) {
1022   DCHECK_EQ(IrOpcode::kJSCreateIterResultObject, node->opcode());
1023   Node* value = NodeProperties::GetValueInput(node, 0);
1024   Node* done = NodeProperties::GetValueInput(node, 1);
1025   Node* effect = NodeProperties::GetEffectInput(node);
1026 
1027   Node* iterator_result_map =
1028       jsgraph()->Constant(native_context_ref().iterator_result_map());
1029 
1030   // Emit code to allocate the JSIteratorResult instance.
1031   AllocationBuilder a(jsgraph(), effect, graph()->start());
1032   a.Allocate(JSIteratorResult::kSize);
1033   a.Store(AccessBuilder::ForMap(), iterator_result_map);
1034   a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
1035           jsgraph()->EmptyFixedArrayConstant());
1036   a.Store(AccessBuilder::ForJSObjectElements(),
1037           jsgraph()->EmptyFixedArrayConstant());
1038   a.Store(AccessBuilder::ForJSIteratorResultValue(), value);
1039   a.Store(AccessBuilder::ForJSIteratorResultDone(), done);
1040   STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
1041   a.FinishAndChange(node);
1042   return Changed(node);
1043 }
1044 
ReduceJSCreateStringIterator(Node * node)1045 Reduction JSCreateLowering::ReduceJSCreateStringIterator(Node* node) {
1046   DCHECK_EQ(IrOpcode::kJSCreateStringIterator, node->opcode());
1047   Node* string = NodeProperties::GetValueInput(node, 0);
1048   Node* effect = NodeProperties::GetEffectInput(node);
1049 
1050   Node* map = jsgraph()->Constant(native_context_ref().string_iterator_map());
1051   // Allocate new iterator and attach the iterator to this string.
1052   AllocationBuilder a(jsgraph(), effect, graph()->start());
1053   a.Allocate(JSStringIterator::kSize, NOT_TENURED, Type::OtherObject());
1054   a.Store(AccessBuilder::ForMap(), map);
1055   a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
1056           jsgraph()->EmptyFixedArrayConstant());
1057   a.Store(AccessBuilder::ForJSObjectElements(),
1058           jsgraph()->EmptyFixedArrayConstant());
1059   a.Store(AccessBuilder::ForJSStringIteratorString(), string);
1060   a.Store(AccessBuilder::ForJSStringIteratorIndex(), jsgraph()->SmiConstant(0));
1061   STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
1062   a.FinishAndChange(node);
1063   return Changed(node);
1064 }
1065 
ReduceJSCreateKeyValueArray(Node * node)1066 Reduction JSCreateLowering::ReduceJSCreateKeyValueArray(Node* node) {
1067   DCHECK_EQ(IrOpcode::kJSCreateKeyValueArray, node->opcode());
1068   Node* key = NodeProperties::GetValueInput(node, 0);
1069   Node* value = NodeProperties::GetValueInput(node, 1);
1070   Node* effect = NodeProperties::GetEffectInput(node);
1071 
1072   Node* array_map =
1073       jsgraph()->Constant(native_context_ref().js_array_packed_elements_map());
1074   Node* properties = jsgraph()->EmptyFixedArrayConstant();
1075   Node* length = jsgraph()->Constant(2);
1076 
1077   AllocationBuilder aa(jsgraph(), effect, graph()->start());
1078   aa.AllocateArray(2, factory()->fixed_array_map());
1079   aa.Store(AccessBuilder::ForFixedArrayElement(PACKED_ELEMENTS),
1080            jsgraph()->ZeroConstant(), key);
1081   aa.Store(AccessBuilder::ForFixedArrayElement(PACKED_ELEMENTS),
1082            jsgraph()->OneConstant(), value);
1083   Node* elements = aa.Finish();
1084 
1085   AllocationBuilder a(jsgraph(), elements, graph()->start());
1086   a.Allocate(JSArray::kSize);
1087   a.Store(AccessBuilder::ForMap(), array_map);
1088   a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
1089   a.Store(AccessBuilder::ForJSObjectElements(), elements);
1090   a.Store(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS), length);
1091   STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize);
1092   a.FinishAndChange(node);
1093   return Changed(node);
1094 }
1095 
ReduceJSCreatePromise(Node * node)1096 Reduction JSCreateLowering::ReduceJSCreatePromise(Node* node) {
1097   DCHECK_EQ(IrOpcode::kJSCreatePromise, node->opcode());
1098   Node* effect = NodeProperties::GetEffectInput(node);
1099 
1100   MapRef promise_map = native_context_ref().promise_function().initial_map();
1101 
1102   AllocationBuilder a(jsgraph(), effect, graph()->start());
1103   a.Allocate(promise_map.instance_size());
1104   a.Store(AccessBuilder::ForMap(), promise_map);
1105   a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
1106           jsgraph()->EmptyFixedArrayConstant());
1107   a.Store(AccessBuilder::ForJSObjectElements(),
1108           jsgraph()->EmptyFixedArrayConstant());
1109   a.Store(AccessBuilder::ForJSObjectOffset(JSPromise::kReactionsOrResultOffset),
1110           jsgraph()->ZeroConstant());
1111   STATIC_ASSERT(v8::Promise::kPending == 0);
1112   a.Store(AccessBuilder::ForJSObjectOffset(JSPromise::kFlagsOffset),
1113           jsgraph()->ZeroConstant());
1114   STATIC_ASSERT(JSPromise::kSize == 5 * kPointerSize);
1115   for (int i = 0; i < v8::Promise::kEmbedderFieldCount; ++i) {
1116     a.Store(
1117         AccessBuilder::ForJSObjectOffset(JSPromise::kSize + i * kPointerSize),
1118         jsgraph()->ZeroConstant());
1119   }
1120   a.FinishAndChange(node);
1121   return Changed(node);
1122 }
1123 
ReduceJSCreateLiteralArrayOrObject(Node * node)1124 Reduction JSCreateLowering::ReduceJSCreateLiteralArrayOrObject(Node* node) {
1125   DCHECK(node->opcode() == IrOpcode::kJSCreateLiteralArray ||
1126          node->opcode() == IrOpcode::kJSCreateLiteralObject);
1127   CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
1128   Node* effect = NodeProperties::GetEffectInput(node);
1129   Node* control = NodeProperties::GetControlInput(node);
1130 
1131   FeedbackVectorRef feedback_vector(js_heap_broker(), p.feedback().vector());
1132   ObjectRef feedback = feedback_vector.get(p.feedback().slot());
1133   if (feedback.IsAllocationSite()) {
1134     AllocationSiteRef site = feedback.AsAllocationSite();
1135     if (site.IsFastLiteral()) {
1136       PretenureFlag pretenure = NOT_TENURED;
1137       if (FLAG_allocation_site_pretenuring) {
1138         pretenure = dependencies()->DependOnPretenureMode(site);
1139       }
1140       dependencies()->DependOnElementsKinds(site);
1141       JSObjectRef boilerplate = site.boilerplate().value();
1142       Node* value = effect =
1143           AllocateFastLiteral(effect, control, boilerplate, pretenure);
1144       ReplaceWithValue(node, value, effect, control);
1145       return Replace(value);
1146     }
1147   }
1148   return NoChange();
1149 }
1150 
ReduceJSCreateEmptyLiteralArray(Node * node)1151 Reduction JSCreateLowering::ReduceJSCreateEmptyLiteralArray(Node* node) {
1152   DCHECK_EQ(IrOpcode::kJSCreateEmptyLiteralArray, node->opcode());
1153   FeedbackParameter const& p = FeedbackParameterOf(node->op());
1154   FeedbackVectorRef fv(js_heap_broker(), p.feedback().vector());
1155   ObjectRef feedback = fv.get(p.feedback().slot());
1156   if (feedback.IsAllocationSite()) {
1157     AllocationSiteRef site = feedback.AsAllocationSite();
1158     DCHECK(!site.PointsToLiteral());
1159     MapRef initial_map =
1160         native_context_ref().GetInitialJSArrayMap(site.GetElementsKind());
1161     PretenureFlag const pretenure = dependencies()->DependOnPretenureMode(site);
1162     dependencies()->DependOnElementsKind(site);
1163     Node* length = jsgraph()->ZeroConstant();
1164     DCHECK(!initial_map.IsInobjectSlackTrackingInProgress());
1165     SlackTrackingPrediction slack_tracking_prediction(
1166         initial_map, initial_map.instance_size());
1167     return ReduceNewArray(node, length, 0, initial_map, pretenure,
1168                           slack_tracking_prediction);
1169   }
1170   return NoChange();
1171 }
1172 
ReduceJSCreateEmptyLiteralObject(Node * node)1173 Reduction JSCreateLowering::ReduceJSCreateEmptyLiteralObject(Node* node) {
1174   DCHECK_EQ(IrOpcode::kJSCreateEmptyLiteralObject, node->opcode());
1175   Node* effect = NodeProperties::GetEffectInput(node);
1176   Node* control = NodeProperties::GetControlInput(node);
1177 
1178   // Retrieve the initial map for the object.
1179   MapRef map = native_context_ref().object_function().initial_map();
1180   DCHECK(!map.is_dictionary_map());
1181   DCHECK(!map.IsInobjectSlackTrackingInProgress());
1182   Node* js_object_map = jsgraph()->Constant(map);
1183 
1184   // Setup elements and properties.
1185   Node* elements = jsgraph()->EmptyFixedArrayConstant();
1186   Node* properties = jsgraph()->EmptyFixedArrayConstant();
1187 
1188   // Perform the allocation of the actual JSArray object.
1189   AllocationBuilder a(jsgraph(), effect, control);
1190   a.Allocate(map.instance_size());
1191   a.Store(AccessBuilder::ForMap(), js_object_map);
1192   a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
1193   a.Store(AccessBuilder::ForJSObjectElements(), elements);
1194   for (int i = 0; i < map.GetInObjectProperties(); i++) {
1195     a.Store(AccessBuilder::ForJSObjectInObjectProperty(map, i),
1196             jsgraph()->UndefinedConstant());
1197   }
1198 
1199   RelaxControls(node);
1200   a.FinishAndChange(node);
1201   return Changed(node);
1202 }
1203 
ReduceJSCreateLiteralRegExp(Node * node)1204 Reduction JSCreateLowering::ReduceJSCreateLiteralRegExp(Node* node) {
1205   DCHECK_EQ(IrOpcode::kJSCreateLiteralRegExp, node->opcode());
1206   CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
1207   Node* effect = NodeProperties::GetEffectInput(node);
1208   Node* control = NodeProperties::GetControlInput(node);
1209 
1210   FeedbackVectorRef feedback_vector(js_heap_broker(), p.feedback().vector());
1211   ObjectRef feedback = feedback_vector.get(p.feedback().slot());
1212   if (feedback.IsJSRegExp()) {
1213     JSRegExpRef boilerplate = feedback.AsJSRegExp();
1214     Node* value = effect = AllocateLiteralRegExp(effect, control, boilerplate);
1215     ReplaceWithValue(node, value, effect, control);
1216     return Replace(value);
1217   }
1218   return NoChange();
1219 }
1220 
ReduceJSCreateFunctionContext(Node * node)1221 Reduction JSCreateLowering::ReduceJSCreateFunctionContext(Node* node) {
1222   DCHECK_EQ(IrOpcode::kJSCreateFunctionContext, node->opcode());
1223   const CreateFunctionContextParameters& parameters =
1224       CreateFunctionContextParametersOf(node->op());
1225   ScopeInfoRef scope_info(js_heap_broker(), parameters.scope_info());
1226   int slot_count = parameters.slot_count();
1227   ScopeType scope_type = parameters.scope_type();
1228 
1229   // Use inline allocation for function contexts up to a size limit.
1230   if (slot_count < kFunctionContextAllocationLimit) {
1231     // JSCreateFunctionContext[slot_count < limit]](fun)
1232     Node* effect = NodeProperties::GetEffectInput(node);
1233     Node* control = NodeProperties::GetControlInput(node);
1234     Node* context = NodeProperties::GetContextInput(node);
1235     Node* extension = jsgraph()->TheHoleConstant();
1236     AllocationBuilder a(jsgraph(), effect, control);
1237     STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4);  // Ensure fully covered.
1238     int context_length = slot_count + Context::MIN_CONTEXT_SLOTS;
1239     Handle<Map> map;
1240     switch (scope_type) {
1241       case EVAL_SCOPE:
1242         map = factory()->eval_context_map();
1243         break;
1244       case FUNCTION_SCOPE:
1245         map = factory()->function_context_map();
1246         break;
1247       default:
1248         UNREACHABLE();
1249     }
1250     a.AllocateContext(context_length, map);
1251     a.Store(AccessBuilder::ForContextSlot(Context::SCOPE_INFO_INDEX),
1252             scope_info);
1253     a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
1254     a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
1255     a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
1256             jsgraph()->HeapConstant(native_context()));
1257     for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) {
1258       a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->UndefinedConstant());
1259     }
1260     RelaxControls(node);
1261     a.FinishAndChange(node);
1262     return Changed(node);
1263   }
1264 
1265   return NoChange();
1266 }
1267 
ReduceJSCreateWithContext(Node * node)1268 Reduction JSCreateLowering::ReduceJSCreateWithContext(Node* node) {
1269   DCHECK_EQ(IrOpcode::kJSCreateWithContext, node->opcode());
1270   ScopeInfoRef scope_info(js_heap_broker(), ScopeInfoOf(node->op()));
1271   Node* extension = NodeProperties::GetValueInput(node, 0);
1272   Node* effect = NodeProperties::GetEffectInput(node);
1273   Node* control = NodeProperties::GetControlInput(node);
1274   Node* context = NodeProperties::GetContextInput(node);
1275 
1276   AllocationBuilder a(jsgraph(), effect, control);
1277   STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4);  // Ensure fully covered.
1278   a.AllocateContext(Context::MIN_CONTEXT_SLOTS, factory()->with_context_map());
1279   a.Store(AccessBuilder::ForContextSlot(Context::SCOPE_INFO_INDEX), scope_info);
1280   a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
1281   a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
1282   a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
1283           jsgraph()->HeapConstant(native_context()));
1284   RelaxControls(node);
1285   a.FinishAndChange(node);
1286   return Changed(node);
1287 }
1288 
ReduceJSCreateCatchContext(Node * node)1289 Reduction JSCreateLowering::ReduceJSCreateCatchContext(Node* node) {
1290   DCHECK_EQ(IrOpcode::kJSCreateCatchContext, node->opcode());
1291   ScopeInfoRef scope_info(js_heap_broker(), ScopeInfoOf(node->op()));
1292   Node* exception = NodeProperties::GetValueInput(node, 0);
1293   Node* effect = NodeProperties::GetEffectInput(node);
1294   Node* control = NodeProperties::GetControlInput(node);
1295   Node* context = NodeProperties::GetContextInput(node);
1296   Node* extension = jsgraph()->TheHoleConstant();
1297 
1298   AllocationBuilder a(jsgraph(), effect, control);
1299   STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4);  // Ensure fully covered.
1300   a.AllocateContext(Context::MIN_CONTEXT_SLOTS + 1,
1301                     factory()->catch_context_map());
1302   a.Store(AccessBuilder::ForContextSlot(Context::SCOPE_INFO_INDEX), scope_info);
1303   a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
1304   a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
1305   a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
1306           jsgraph()->HeapConstant(native_context()));
1307   a.Store(AccessBuilder::ForContextSlot(Context::THROWN_OBJECT_INDEX),
1308           exception);
1309   RelaxControls(node);
1310   a.FinishAndChange(node);
1311   return Changed(node);
1312 }
1313 
ReduceJSCreateBlockContext(Node * node)1314 Reduction JSCreateLowering::ReduceJSCreateBlockContext(Node* node) {
1315   DCHECK_EQ(IrOpcode::kJSCreateBlockContext, node->opcode());
1316   ScopeInfoRef scope_info(js_heap_broker(), ScopeInfoOf(node->op()));
1317   int const context_length = scope_info.ContextLength();
1318 
1319   // Use inline allocation for block contexts up to a size limit.
1320   if (context_length < kBlockContextAllocationLimit) {
1321     // JSCreateBlockContext[scope[length < limit]](fun)
1322     Node* effect = NodeProperties::GetEffectInput(node);
1323     Node* control = NodeProperties::GetControlInput(node);
1324     Node* context = NodeProperties::GetContextInput(node);
1325     Node* extension = jsgraph()->TheHoleConstant();
1326 
1327     AllocationBuilder a(jsgraph(), effect, control);
1328     STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4);  // Ensure fully covered.
1329     a.AllocateContext(context_length, factory()->block_context_map());
1330     a.Store(AccessBuilder::ForContextSlot(Context::SCOPE_INFO_INDEX),
1331             scope_info);
1332     a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
1333     a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
1334     a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
1335             jsgraph()->HeapConstant(native_context()));
1336     for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) {
1337       a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->UndefinedConstant());
1338     }
1339     RelaxControls(node);
1340     a.FinishAndChange(node);
1341     return Changed(node);
1342   }
1343 
1344   return NoChange();
1345 }
1346 
ReduceJSCreateObject(Node * node)1347 Reduction JSCreateLowering::ReduceJSCreateObject(Node* node) {
1348   DCHECK_EQ(IrOpcode::kJSCreateObject, node->opcode());
1349   Node* effect = NodeProperties::GetEffectInput(node);
1350   Node* control = NodeProperties::GetControlInput(node);
1351   Node* prototype = NodeProperties::GetValueInput(node, 0);
1352   Type prototype_type = NodeProperties::GetType(prototype);
1353   if (!prototype_type.IsHeapConstant()) return NoChange();
1354 
1355   HeapObjectRef prototype_const = prototype_type.AsHeapConstant()->Ref();
1356   auto maybe_instance_map = prototype_const.TryGetObjectCreateMap();
1357   if (!maybe_instance_map) return NoChange();
1358   MapRef instance_map = maybe_instance_map.value();
1359 
1360   Node* properties = jsgraph()->EmptyFixedArrayConstant();
1361   if (instance_map.is_dictionary_map()) {
1362     DCHECK_EQ(prototype_const.type().oddball_type(), OddballType::kNull);
1363     // Allocate an empty NameDictionary as backing store for the properties.
1364     Handle<Map> map = isolate()->factory()->name_dictionary_map();
1365     int capacity =
1366         NameDictionary::ComputeCapacity(NameDictionary::kInitialCapacity);
1367     DCHECK(base::bits::IsPowerOfTwo(capacity));
1368     int length = NameDictionary::EntryToIndex(capacity);
1369     int size = NameDictionary::SizeFor(length);
1370 
1371     AllocationBuilder a(jsgraph(), effect, control);
1372     a.Allocate(size, NOT_TENURED, Type::Any());
1373     a.Store(AccessBuilder::ForMap(), map);
1374     // Initialize FixedArray fields.
1375     a.Store(AccessBuilder::ForFixedArrayLength(),
1376             jsgraph()->SmiConstant(length));
1377     // Initialize HashTable fields.
1378     a.Store(AccessBuilder::ForHashTableBaseNumberOfElements(),
1379             jsgraph()->SmiConstant(0));
1380     a.Store(AccessBuilder::ForHashTableBaseNumberOfDeletedElement(),
1381             jsgraph()->SmiConstant(0));
1382     a.Store(AccessBuilder::ForHashTableBaseCapacity(),
1383             jsgraph()->SmiConstant(capacity));
1384     // Initialize Dictionary fields.
1385     a.Store(AccessBuilder::ForDictionaryNextEnumerationIndex(),
1386             jsgraph()->SmiConstant(PropertyDetails::kInitialIndex));
1387     a.Store(AccessBuilder::ForDictionaryObjectHashIndex(),
1388             jsgraph()->SmiConstant(PropertyArray::kNoHashSentinel));
1389     // Initialize the Properties fields.
1390     Node* undefined = jsgraph()->UndefinedConstant();
1391     STATIC_ASSERT(NameDictionary::kElementsStartIndex ==
1392                   NameDictionary::kObjectHashIndex + 1);
1393     for (int index = NameDictionary::kElementsStartIndex; index < length;
1394          index++) {
1395       a.Store(AccessBuilder::ForFixedArraySlot(index, kNoWriteBarrier),
1396               undefined);
1397     }
1398     properties = effect = a.Finish();
1399   }
1400 
1401   int const instance_size = instance_map.instance_size();
1402   if (instance_size > kMaxRegularHeapObjectSize) return NoChange();
1403   CHECK(!instance_map.IsInobjectSlackTrackingInProgress());
1404 
1405   // Emit code to allocate the JSObject instance for the given
1406   // {instance_map}.
1407   AllocationBuilder a(jsgraph(), effect, control);
1408   a.Allocate(instance_size, NOT_TENURED, Type::Any());
1409   a.Store(AccessBuilder::ForMap(), instance_map);
1410   a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
1411   a.Store(AccessBuilder::ForJSObjectElements(),
1412           jsgraph()->EmptyFixedArrayConstant());
1413   // Initialize Object fields.
1414   Node* undefined = jsgraph()->UndefinedConstant();
1415   for (int offset = JSObject::kHeaderSize; offset < instance_size;
1416        offset += kPointerSize) {
1417     a.Store(AccessBuilder::ForJSObjectOffset(offset, kNoWriteBarrier),
1418             undefined);
1419   }
1420   Node* value = effect = a.Finish();
1421 
1422   ReplaceWithValue(node, value, effect, control);
1423   return Replace(value);
1424 }
1425 
1426 // Helper that allocates a FixedArray holding argument values recorded in the
1427 // given {frame_state}. Serves as backing store for JSCreateArguments nodes.
AllocateArguments(Node * effect,Node * control,Node * frame_state)1428 Node* JSCreateLowering::AllocateArguments(Node* effect, Node* control,
1429                                           Node* frame_state) {
1430   FrameStateInfo state_info = FrameStateInfoOf(frame_state->op());
1431   int argument_count = state_info.parameter_count() - 1;  // Minus receiver.
1432   if (argument_count == 0) return jsgraph()->EmptyFixedArrayConstant();
1433 
1434   // Prepare an iterator over argument values recorded in the frame state.
1435   Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
1436   StateValuesAccess parameters_access(parameters);
1437   auto parameters_it = ++parameters_access.begin();
1438 
1439   // Actually allocate the backing store.
1440   AllocationBuilder a(jsgraph(), effect, control);
1441   a.AllocateArray(argument_count, factory()->fixed_array_map());
1442   for (int i = 0; i < argument_count; ++i, ++parameters_it) {
1443     DCHECK_NOT_NULL((*parameters_it).node);
1444     a.Store(AccessBuilder::ForFixedArraySlot(i), (*parameters_it).node);
1445   }
1446   return a.Finish();
1447 }
1448 
1449 // Helper that allocates a FixedArray holding argument values recorded in the
1450 // given {frame_state}. Serves as backing store for JSCreateArguments nodes.
AllocateRestArguments(Node * effect,Node * control,Node * frame_state,int start_index)1451 Node* JSCreateLowering::AllocateRestArguments(Node* effect, Node* control,
1452                                               Node* frame_state,
1453                                               int start_index) {
1454   FrameStateInfo state_info = FrameStateInfoOf(frame_state->op());
1455   int argument_count = state_info.parameter_count() - 1;  // Minus receiver.
1456   int num_elements = std::max(0, argument_count - start_index);
1457   if (num_elements == 0) return jsgraph()->EmptyFixedArrayConstant();
1458 
1459   // Prepare an iterator over argument values recorded in the frame state.
1460   Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
1461   StateValuesAccess parameters_access(parameters);
1462   auto parameters_it = ++parameters_access.begin();
1463 
1464   // Skip unused arguments.
1465   for (int i = 0; i < start_index; i++) {
1466     ++parameters_it;
1467   }
1468 
1469   // Actually allocate the backing store.
1470   AllocationBuilder a(jsgraph(), effect, control);
1471   a.AllocateArray(num_elements, factory()->fixed_array_map());
1472   for (int i = 0; i < num_elements; ++i, ++parameters_it) {
1473     DCHECK_NOT_NULL((*parameters_it).node);
1474     a.Store(AccessBuilder::ForFixedArraySlot(i), (*parameters_it).node);
1475   }
1476   return a.Finish();
1477 }
1478 
1479 // Helper that allocates a FixedArray serving as a parameter map for values
1480 // recorded in the given {frame_state}. Some elements map to slots within the
1481 // given {context}. Serves as backing store for JSCreateArguments nodes.
AllocateAliasedArguments(Node * effect,Node * control,Node * frame_state,Node * context,const SharedFunctionInfoRef & shared,bool * has_aliased_arguments)1482 Node* JSCreateLowering::AllocateAliasedArguments(
1483     Node* effect, Node* control, Node* frame_state, Node* context,
1484     const SharedFunctionInfoRef& shared, bool* has_aliased_arguments) {
1485   FrameStateInfo state_info = FrameStateInfoOf(frame_state->op());
1486   int argument_count = state_info.parameter_count() - 1;  // Minus receiver.
1487   if (argument_count == 0) return jsgraph()->EmptyFixedArrayConstant();
1488 
1489   // If there is no aliasing, the arguments object elements are not special in
1490   // any way, we can just return an unmapped backing store instead.
1491   int parameter_count = shared.internal_formal_parameter_count();
1492   if (parameter_count == 0) {
1493     return AllocateArguments(effect, control, frame_state);
1494   }
1495 
1496   // Calculate number of argument values being aliased/mapped.
1497   int mapped_count = Min(argument_count, parameter_count);
1498   *has_aliased_arguments = true;
1499 
1500   // Prepare an iterator over argument values recorded in the frame state.
1501   Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
1502   StateValuesAccess parameters_access(parameters);
1503   auto parameters_it = ++parameters_access.begin();
1504 
1505   // The unmapped argument values recorded in the frame state are stored yet
1506   // another indirection away and then linked into the parameter map below,
1507   // whereas mapped argument values are replaced with a hole instead.
1508   AllocationBuilder aa(jsgraph(), effect, control);
1509   aa.AllocateArray(argument_count, factory()->fixed_array_map());
1510   for (int i = 0; i < mapped_count; ++i, ++parameters_it) {
1511     aa.Store(AccessBuilder::ForFixedArraySlot(i), jsgraph()->TheHoleConstant());
1512   }
1513   for (int i = mapped_count; i < argument_count; ++i, ++parameters_it) {
1514     DCHECK_NOT_NULL((*parameters_it).node);
1515     aa.Store(AccessBuilder::ForFixedArraySlot(i), (*parameters_it).node);
1516   }
1517   Node* arguments = aa.Finish();
1518 
1519   // Actually allocate the backing store.
1520   AllocationBuilder a(jsgraph(), arguments, control);
1521   a.AllocateArray(mapped_count + 2, factory()->sloppy_arguments_elements_map());
1522   a.Store(AccessBuilder::ForFixedArraySlot(0), context);
1523   a.Store(AccessBuilder::ForFixedArraySlot(1), arguments);
1524   for (int i = 0; i < mapped_count; ++i) {
1525     int idx = Context::MIN_CONTEXT_SLOTS + parameter_count - 1 - i;
1526     a.Store(AccessBuilder::ForFixedArraySlot(i + 2), jsgraph()->Constant(idx));
1527   }
1528   return a.Finish();
1529 }
1530 
1531 // Helper that allocates a FixedArray serving as a parameter map for values
1532 // unknown at compile-time, the true {arguments_length} and {arguments_frame}
1533 // values can only be determined dynamically at run-time and are provided.
1534 // Serves as backing store for JSCreateArguments nodes.
AllocateAliasedArguments(Node * effect,Node * control,Node * context,Node * arguments_frame,Node * arguments_length,const SharedFunctionInfoRef & shared,bool * has_aliased_arguments)1535 Node* JSCreateLowering::AllocateAliasedArguments(
1536     Node* effect, Node* control, Node* context, Node* arguments_frame,
1537     Node* arguments_length, const SharedFunctionInfoRef& shared,
1538     bool* has_aliased_arguments) {
1539   // If there is no aliasing, the arguments object elements are not
1540   // special in any way, we can just return an unmapped backing store.
1541   int parameter_count = shared.internal_formal_parameter_count();
1542   if (parameter_count == 0) {
1543     return graph()->NewNode(simplified()->NewArgumentsElements(0),
1544                             arguments_frame, arguments_length, effect);
1545   }
1546 
1547   // From here on we are going to allocate a mapped (aka. aliased) elements
1548   // backing store. We do not statically know how many arguments exist, but
1549   // dynamically selecting the hole for some of the "mapped" elements allows
1550   // using a static shape for the parameter map.
1551   int mapped_count = parameter_count;
1552   *has_aliased_arguments = true;
1553 
1554   // The unmapped argument values are stored yet another indirection away and
1555   // then linked into the parameter map below, whereas mapped argument values
1556   // (i.e. the first {mapped_count} elements) are replaced with a hole instead.
1557   Node* arguments =
1558       graph()->NewNode(simplified()->NewArgumentsElements(mapped_count),
1559                        arguments_frame, arguments_length, effect);
1560 
1561   // Actually allocate the backing store.
1562   AllocationBuilder a(jsgraph(), arguments, control);
1563   a.AllocateArray(mapped_count + 2, factory()->sloppy_arguments_elements_map());
1564   a.Store(AccessBuilder::ForFixedArraySlot(0), context);
1565   a.Store(AccessBuilder::ForFixedArraySlot(1), arguments);
1566   for (int i = 0; i < mapped_count; ++i) {
1567     int idx = Context::MIN_CONTEXT_SLOTS + parameter_count - 1 - i;
1568     Node* value = graph()->NewNode(
1569         common()->Select(MachineRepresentation::kTagged),
1570         graph()->NewNode(simplified()->NumberLessThan(), jsgraph()->Constant(i),
1571                          arguments_length),
1572         jsgraph()->Constant(idx), jsgraph()->TheHoleConstant());
1573     a.Store(AccessBuilder::ForFixedArraySlot(i + 2), value);
1574   }
1575   return a.Finish();
1576 }
1577 
AllocateElements(Node * effect,Node * control,ElementsKind elements_kind,int capacity,PretenureFlag pretenure)1578 Node* JSCreateLowering::AllocateElements(Node* effect, Node* control,
1579                                          ElementsKind elements_kind,
1580                                          int capacity,
1581                                          PretenureFlag pretenure) {
1582   DCHECK_LE(1, capacity);
1583   DCHECK_LE(capacity, JSArray::kInitialMaxFastElementArray);
1584 
1585   Handle<Map> elements_map = IsDoubleElementsKind(elements_kind)
1586                                  ? factory()->fixed_double_array_map()
1587                                  : factory()->fixed_array_map();
1588   ElementAccess access = IsDoubleElementsKind(elements_kind)
1589                              ? AccessBuilder::ForFixedDoubleArrayElement()
1590                              : AccessBuilder::ForFixedArrayElement();
1591   Node* value = jsgraph()->TheHoleConstant();
1592 
1593   // Actually allocate the backing store.
1594   AllocationBuilder a(jsgraph(), effect, control);
1595   a.AllocateArray(capacity, elements_map, pretenure);
1596   for (int i = 0; i < capacity; ++i) {
1597     Node* index = jsgraph()->Constant(i);
1598     a.Store(access, index, value);
1599   }
1600   return a.Finish();
1601 }
1602 
AllocateElements(Node * effect,Node * control,ElementsKind elements_kind,std::vector<Node * > const & values,PretenureFlag pretenure)1603 Node* JSCreateLowering::AllocateElements(Node* effect, Node* control,
1604                                          ElementsKind elements_kind,
1605                                          std::vector<Node*> const& values,
1606                                          PretenureFlag pretenure) {
1607   int const capacity = static_cast<int>(values.size());
1608   DCHECK_LE(1, capacity);
1609   DCHECK_LE(capacity, JSArray::kInitialMaxFastElementArray);
1610 
1611   Handle<Map> elements_map = IsDoubleElementsKind(elements_kind)
1612                                  ? factory()->fixed_double_array_map()
1613                                  : factory()->fixed_array_map();
1614   ElementAccess access = IsDoubleElementsKind(elements_kind)
1615                              ? AccessBuilder::ForFixedDoubleArrayElement()
1616                              : AccessBuilder::ForFixedArrayElement();
1617 
1618   // Actually allocate the backing store.
1619   AllocationBuilder a(jsgraph(), effect, control);
1620   a.AllocateArray(capacity, elements_map, pretenure);
1621   for (int i = 0; i < capacity; ++i) {
1622     Node* index = jsgraph()->Constant(i);
1623     a.Store(access, index, values[i]);
1624   }
1625   return a.Finish();
1626 }
1627 
AllocateFastLiteral(Node * effect,Node * control,JSObjectRef boilerplate,PretenureFlag pretenure)1628 Node* JSCreateLowering::AllocateFastLiteral(Node* effect, Node* control,
1629                                             JSObjectRef boilerplate,
1630                                             PretenureFlag pretenure) {
1631   // Setup the properties backing store.
1632   Node* properties = jsgraph()->EmptyFixedArrayConstant();
1633 
1634   // Compute the in-object properties to store first (might have effects).
1635   MapRef boilerplate_map = boilerplate.map();
1636   ZoneVector<std::pair<FieldAccess, Node*>> inobject_fields(zone());
1637   inobject_fields.reserve(boilerplate_map.GetInObjectProperties());
1638   int const boilerplate_nof = boilerplate_map.NumberOfOwnDescriptors();
1639   for (int i = 0; i < boilerplate_nof; ++i) {
1640     PropertyDetails const property_details =
1641         boilerplate_map.GetPropertyDetails(i);
1642     if (property_details.location() != kField) continue;
1643     DCHECK_EQ(kData, property_details.kind());
1644     NameRef property_name = boilerplate_map.GetPropertyKey(i);
1645     FieldIndex index = boilerplate_map.GetFieldIndexFor(i);
1646     FieldAccess access = {
1647         kTaggedBase,        index.offset(), property_name.object<Name>(),
1648         MaybeHandle<Map>(), Type::Any(),    MachineType::AnyTagged(),
1649         kFullWriteBarrier};
1650     Node* value;
1651     if (boilerplate.IsUnboxedDoubleField(index)) {
1652       access.machine_type = MachineType::Float64();
1653       access.type = Type::Number();
1654       value = jsgraph()->Constant(boilerplate.RawFastDoublePropertyAt(index));
1655     } else {
1656       ObjectRef boilerplate_value = boilerplate.RawFastPropertyAt(index);
1657       if (boilerplate_value.IsJSObject()) {
1658         JSObjectRef boilerplate_object = boilerplate_value.AsJSObject();
1659         value = effect =
1660             AllocateFastLiteral(effect, control, boilerplate_object, pretenure);
1661       } else if (property_details.representation().IsDouble()) {
1662         double number = boilerplate_value.AsMutableHeapNumber().value();
1663         // Allocate a mutable HeapNumber box and store the value into it.
1664         AllocationBuilder builder(jsgraph(), effect, control);
1665         builder.Allocate(HeapNumber::kSize, pretenure);
1666         builder.Store(AccessBuilder::ForMap(),
1667                       factory()->mutable_heap_number_map());
1668         builder.Store(AccessBuilder::ForHeapNumberValue(),
1669                       jsgraph()->Constant(number));
1670         value = effect = builder.Finish();
1671       } else if (property_details.representation().IsSmi()) {
1672         // Ensure that value is stored as smi.
1673         value = boilerplate_value.oddball_type() == OddballType::kUninitialized
1674                     ? jsgraph()->ZeroConstant()
1675                     : jsgraph()->Constant(boilerplate_value.AsSmi());
1676       } else {
1677         value = jsgraph()->Constant(boilerplate_value);
1678       }
1679     }
1680     inobject_fields.push_back(std::make_pair(access, value));
1681   }
1682 
1683   // Fill slack at the end of the boilerplate object with filler maps.
1684   int const boilerplate_length = boilerplate_map.GetInObjectProperties();
1685   for (int index = static_cast<int>(inobject_fields.size());
1686        index < boilerplate_length; ++index) {
1687     FieldAccess access =
1688         AccessBuilder::ForJSObjectInObjectProperty(boilerplate_map, index);
1689     Node* value = jsgraph()->HeapConstant(factory()->one_pointer_filler_map());
1690     inobject_fields.push_back(std::make_pair(access, value));
1691   }
1692 
1693   // Setup the elements backing store.
1694   Node* elements =
1695       AllocateFastLiteralElements(effect, control, boilerplate, pretenure);
1696   if (elements->op()->EffectOutputCount() > 0) effect = elements;
1697 
1698   // Actually allocate and initialize the object.
1699   AllocationBuilder builder(jsgraph(), effect, control);
1700   builder.Allocate(boilerplate_map.instance_size(), pretenure,
1701                    Type::For(js_heap_broker(), boilerplate_map.object<Map>()));
1702   builder.Store(AccessBuilder::ForMap(), boilerplate_map);
1703   builder.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
1704   builder.Store(AccessBuilder::ForJSObjectElements(), elements);
1705   if (boilerplate_map.IsJSArrayMap()) {
1706     JSArrayRef boilerplate_array = boilerplate.AsJSArray();
1707     builder.Store(
1708         AccessBuilder::ForJSArrayLength(boilerplate_array.GetElementsKind()),
1709         boilerplate_array.length());
1710   }
1711   for (auto const& inobject_field : inobject_fields) {
1712     builder.Store(inobject_field.first, inobject_field.second);
1713   }
1714   return builder.Finish();
1715 }
1716 
AllocateFastLiteralElements(Node * effect,Node * control,JSObjectRef boilerplate,PretenureFlag pretenure)1717 Node* JSCreateLowering::AllocateFastLiteralElements(Node* effect, Node* control,
1718                                                     JSObjectRef boilerplate,
1719                                                     PretenureFlag pretenure) {
1720   FixedArrayBaseRef boilerplate_elements = boilerplate.elements();
1721 
1722   // Empty or copy-on-write elements just store a constant.
1723   int const elements_length = boilerplate_elements.length();
1724   MapRef elements_map = boilerplate_elements.map();
1725   if (boilerplate_elements.length() == 0 || elements_map.IsFixedCowArrayMap()) {
1726     if (pretenure == TENURED) {
1727       boilerplate.EnsureElementsTenured();
1728       boilerplate_elements = boilerplate.elements();
1729     }
1730     return jsgraph()->HeapConstant(boilerplate_elements.object<HeapObject>());
1731   }
1732 
1733   // Compute the elements to store first (might have effects).
1734   ZoneVector<Node*> elements_values(elements_length, zone());
1735   if (elements_map.instance_type() == FIXED_DOUBLE_ARRAY_TYPE) {
1736     FixedDoubleArrayRef elements = boilerplate_elements.AsFixedDoubleArray();
1737     for (int i = 0; i < elements_length; ++i) {
1738       if (elements.is_the_hole(i)) {
1739         elements_values[i] = jsgraph()->TheHoleConstant();
1740       } else {
1741         elements_values[i] = jsgraph()->Constant(elements.get_scalar(i));
1742       }
1743     }
1744   } else {
1745     FixedArrayRef elements = boilerplate_elements.AsFixedArray();
1746     for (int i = 0; i < elements_length; ++i) {
1747       if (elements.is_the_hole(i)) {
1748         elements_values[i] = jsgraph()->TheHoleConstant();
1749       } else {
1750         ObjectRef element_value = elements.get(i);
1751         if (element_value.IsJSObject()) {
1752           elements_values[i] = effect = AllocateFastLiteral(
1753               effect, control, element_value.AsJSObject(), pretenure);
1754         } else {
1755           elements_values[i] = jsgraph()->Constant(element_value);
1756         }
1757       }
1758     }
1759   }
1760 
1761   // Allocate the backing store array and store the elements.
1762   AllocationBuilder builder(jsgraph(), effect, control);
1763   builder.AllocateArray(elements_length, elements_map.object<Map>(), pretenure);
1764   ElementAccess const access =
1765       (elements_map.instance_type() == FIXED_DOUBLE_ARRAY_TYPE)
1766           ? AccessBuilder::ForFixedDoubleArrayElement()
1767           : AccessBuilder::ForFixedArrayElement();
1768   for (int i = 0; i < elements_length; ++i) {
1769     builder.Store(access, jsgraph()->Constant(i), elements_values[i]);
1770   }
1771   return builder.Finish();
1772 }
1773 
AllocateLiteralRegExp(Node * effect,Node * control,JSRegExpRef boilerplate)1774 Node* JSCreateLowering::AllocateLiteralRegExp(Node* effect, Node* control,
1775                                               JSRegExpRef boilerplate) {
1776   MapRef boilerplate_map = boilerplate.map();
1777 
1778   // Sanity check that JSRegExp object layout hasn't changed.
1779   STATIC_ASSERT(JSRegExp::kDataOffset == JSObject::kHeaderSize);
1780   STATIC_ASSERT(JSRegExp::kSourceOffset ==
1781                 JSRegExp::kDataOffset + kPointerSize);
1782   STATIC_ASSERT(JSRegExp::kFlagsOffset ==
1783                 JSRegExp::kSourceOffset + kPointerSize);
1784   STATIC_ASSERT(JSRegExp::kSize == JSRegExp::kFlagsOffset + kPointerSize);
1785   STATIC_ASSERT(JSRegExp::kLastIndexOffset == JSRegExp::kSize);
1786   STATIC_ASSERT(JSRegExp::kInObjectFieldCount == 1);  // LastIndex.
1787 
1788   const PretenureFlag pretenure = NOT_TENURED;
1789   const int size =
1790       JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
1791 
1792   AllocationBuilder builder(jsgraph(), effect, control);
1793   builder.Allocate(size, pretenure,
1794                    Type::For(js_heap_broker(), boilerplate_map.object<Map>()));
1795   builder.Store(AccessBuilder::ForMap(), boilerplate_map);
1796   builder.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
1797                 boilerplate.raw_properties_or_hash());
1798   builder.Store(AccessBuilder::ForJSObjectElements(), boilerplate.elements());
1799 
1800   builder.Store(AccessBuilder::ForJSRegExpData(), boilerplate.data());
1801   builder.Store(AccessBuilder::ForJSRegExpSource(), boilerplate.source());
1802   builder.Store(AccessBuilder::ForJSRegExpFlags(), boilerplate.flags());
1803   builder.Store(AccessBuilder::ForJSRegExpLastIndex(),
1804                 boilerplate.last_index());
1805 
1806   return builder.Finish();
1807 }
1808 
factory() const1809 Factory* JSCreateLowering::factory() const { return isolate()->factory(); }
1810 
graph() const1811 Graph* JSCreateLowering::graph() const { return jsgraph()->graph(); }
1812 
isolate() const1813 Isolate* JSCreateLowering::isolate() const { return jsgraph()->isolate(); }
1814 
common() const1815 CommonOperatorBuilder* JSCreateLowering::common() const {
1816   return jsgraph()->common();
1817 }
1818 
simplified() const1819 SimplifiedOperatorBuilder* JSCreateLowering::simplified() const {
1820   return jsgraph()->simplified();
1821 }
1822 
native_context_ref() const1823 NativeContextRef JSCreateLowering::native_context_ref() const {
1824   return NativeContextRef(js_heap_broker(), native_context());
1825 }
1826 
1827 }  // namespace compiler
1828 }  // namespace internal
1829 }  // namespace v8
1830