• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 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/serializer-for-background-compilation.h"
6 
7 #include <sstream>
8 
9 #include "src/base/optional.h"
10 #include "src/compiler/access-info.h"
11 #include "src/compiler/bytecode-analysis.h"
12 #include "src/compiler/compilation-dependencies.h"
13 #include "src/compiler/js-heap-broker.h"
14 #include "src/compiler/serializer-hints.h"
15 #include "src/compiler/zone-stats.h"
16 #include "src/handles/handles-inl.h"
17 #include "src/ic/call-optimization.h"
18 #include "src/interpreter/bytecode-array-iterator.h"
19 #include "src/objects/code.h"
20 #include "src/objects/js-array-inl.h"
21 #include "src/objects/js-regexp-inl.h"
22 #include "src/objects/literal-objects-inl.h"
23 #include "src/objects/shared-function-info-inl.h"
24 #include "src/zone/zone-containers.h"
25 #include "src/zone/zone.h"
26 
27 namespace v8 {
28 namespace internal {
29 namespace compiler {
30 
31 #define KILL_ENVIRONMENT_LIST(V) \
32   V(Abort)                       \
33   V(ReThrow)                     \
34   V(Throw)
35 
36 #define CLEAR_ACCUMULATOR_LIST(V) \
37   V(CallRuntime)                  \
38   V(CloneObject)                  \
39   V(CreateArrayFromIterable)      \
40   V(CreateEmptyObjectLiteral)     \
41   V(CreateMappedArguments)        \
42   V(CreateRestParameter)          \
43   V(CreateUnmappedArguments)      \
44   V(DeletePropertySloppy)         \
45   V(DeletePropertyStrict)         \
46   V(ForInContinue)                \
47   V(ForInEnumerate)               \
48   V(ForInStep)                    \
49   V(LogicalNot)                   \
50   V(SetPendingMessage)            \
51   V(TestNull)                     \
52   V(TestReferenceEqual)           \
53   V(TestTypeOf)                   \
54   V(TestUndefined)                \
55   V(TestUndetectable)             \
56   V(ToBooleanLogicalNot)          \
57   V(ToName)                       \
58   V(ToString)                     \
59   V(TypeOf)
60 
61 #define UNCONDITIONAL_JUMPS_LIST(V) \
62   V(Jump)                           \
63   V(JumpConstant)                   \
64   V(JumpLoop)
65 
66 #define CONDITIONAL_JUMPS_LIST(V) \
67   V(JumpIfFalse)                  \
68   V(JumpIfFalseConstant)          \
69   V(JumpIfJSReceiver)             \
70   V(JumpIfJSReceiverConstant)     \
71   V(JumpIfNotNull)                \
72   V(JumpIfNotNullConstant)        \
73   V(JumpIfNotUndefined)           \
74   V(JumpIfNotUndefinedConstant)   \
75   V(JumpIfNull)                   \
76   V(JumpIfNullConstant)           \
77   V(JumpIfToBooleanFalse)         \
78   V(JumpIfToBooleanFalseConstant) \
79   V(JumpIfToBooleanTrue)          \
80   V(JumpIfToBooleanTrueConstant)  \
81   V(JumpIfTrue)                   \
82   V(JumpIfTrueConstant)           \
83   V(JumpIfUndefined)              \
84   V(JumpIfUndefinedConstant)      \
85   V(JumpIfUndefinedOrNull)        \
86   V(JumpIfUndefinedOrNullConstant)
87 
88 #define IGNORED_BYTECODE_LIST(V)      \
89   V(CallRuntimeForPair)               \
90   V(CollectTypeProfile)               \
91   V(DebugBreak0)                      \
92   V(DebugBreak1)                      \
93   V(DebugBreak2)                      \
94   V(DebugBreak3)                      \
95   V(DebugBreak4)                      \
96   V(DebugBreak5)                      \
97   V(DebugBreak6)                      \
98   V(DebugBreakExtraWide)              \
99   V(DebugBreakWide)                   \
100   V(Debugger)                         \
101   V(IncBlockCounter)                  \
102   V(ResumeGenerator)                  \
103   V(SuspendGenerator)                 \
104   V(ThrowIfNotSuperConstructor)       \
105   V(ThrowSuperAlreadyCalledIfNotHole) \
106   V(ThrowSuperNotCalledIfHole)        \
107   V(ToObject)
108 
109 #define UNREACHABLE_BYTECODE_LIST(V) \
110   V(ExtraWide)                       \
111   V(Illegal)                         \
112   V(Wide)
113 
114 #define BINARY_OP_LIST(V) \
115   V(Add)                  \
116   V(AddSmi)               \
117   V(BitwiseAnd)           \
118   V(BitwiseAndSmi)        \
119   V(BitwiseOr)            \
120   V(BitwiseOrSmi)         \
121   V(BitwiseXor)           \
122   V(BitwiseXorSmi)        \
123   V(Div)                  \
124   V(DivSmi)               \
125   V(Exp)                  \
126   V(ExpSmi)               \
127   V(Mod)                  \
128   V(ModSmi)               \
129   V(Mul)                  \
130   V(MulSmi)               \
131   V(ShiftLeft)            \
132   V(ShiftLeftSmi)         \
133   V(ShiftRight)           \
134   V(ShiftRightSmi)        \
135   V(ShiftRightLogical)    \
136   V(ShiftRightLogicalSmi) \
137   V(Sub)                  \
138   V(SubSmi)
139 
140 #define UNARY_OP_LIST(V) \
141   V(BitwiseNot)          \
142   V(Dec)                 \
143   V(Inc)                 \
144   V(Negate)
145 
146 #define COMPARE_OP_LIST(V)  \
147   V(TestEqual)              \
148   V(TestEqualStrict)        \
149   V(TestGreaterThan)        \
150   V(TestGreaterThanOrEqual) \
151   V(TestLessThan)           \
152   V(TestLessThanOrEqual)
153 
154 #define SUPPORTED_BYTECODE_LIST(V)    \
155   V(CallAnyReceiver)                  \
156   V(CallJSRuntime)                    \
157   V(CallNoFeedback)                   \
158   V(CallProperty)                     \
159   V(CallProperty0)                    \
160   V(CallProperty1)                    \
161   V(CallProperty2)                    \
162   V(CallUndefinedReceiver)            \
163   V(CallUndefinedReceiver0)           \
164   V(CallUndefinedReceiver1)           \
165   V(CallUndefinedReceiver2)           \
166   V(CallWithSpread)                   \
167   V(Construct)                        \
168   V(ConstructWithSpread)              \
169   V(CreateArrayLiteral)               \
170   V(CreateBlockContext)               \
171   V(CreateCatchContext)               \
172   V(CreateClosure)                    \
173   V(CreateEmptyArrayLiteral)          \
174   V(CreateEvalContext)                \
175   V(CreateFunctionContext)            \
176   V(CreateObjectLiteral)              \
177   V(CreateRegExpLiteral)              \
178   V(CreateWithContext)                \
179   V(ForInNext)                        \
180   V(ForInPrepare)                     \
181   V(GetIterator)                      \
182   V(GetSuperConstructor)              \
183   V(GetTemplateObject)                \
184   V(InvokeIntrinsic)                  \
185   V(LdaConstant)                      \
186   V(LdaContextSlot)                   \
187   V(LdaCurrentContextSlot)            \
188   V(LdaImmutableContextSlot)          \
189   V(LdaImmutableCurrentContextSlot)   \
190   V(LdaModuleVariable)                \
191   V(LdaFalse)                         \
192   V(LdaGlobal)                        \
193   V(LdaGlobalInsideTypeof)            \
194   V(LdaKeyedProperty)                 \
195   V(LdaLookupContextSlot)             \
196   V(LdaLookupContextSlotInsideTypeof) \
197   V(LdaLookupGlobalSlot)              \
198   V(LdaLookupGlobalSlotInsideTypeof)  \
199   V(LdaLookupSlot)                    \
200   V(LdaLookupSlotInsideTypeof)        \
201   V(LdaNamedProperty)                 \
202   V(LdaNamedPropertyFromSuper)        \
203   V(LdaNamedPropertyNoFeedback)       \
204   V(LdaNull)                          \
205   V(Ldar)                             \
206   V(LdaSmi)                           \
207   V(LdaTheHole)                       \
208   V(LdaTrue)                          \
209   V(LdaUndefined)                     \
210   V(LdaZero)                          \
211   V(Mov)                              \
212   V(PopContext)                       \
213   V(PushContext)                      \
214   V(Return)                           \
215   V(StaContextSlot)                   \
216   V(StaCurrentContextSlot)            \
217   V(StaDataPropertyInLiteral)         \
218   V(StaGlobal)                        \
219   V(StaInArrayLiteral)                \
220   V(StaKeyedProperty)                 \
221   V(StaLookupSlot)                    \
222   V(StaModuleVariable)                \
223   V(StaNamedOwnProperty)              \
224   V(StaNamedProperty)                 \
225   V(StaNamedPropertyNoFeedback)       \
226   V(Star)                             \
227   V(SwitchOnGeneratorState)           \
228   V(SwitchOnSmiNoFeedback)            \
229   V(TestIn)                           \
230   V(TestInstanceOf)                   \
231   V(ThrowReferenceErrorIfHole)        \
232   V(ToNumber)                         \
233   V(ToNumeric)                        \
234   BINARY_OP_LIST(V)                   \
235   COMPARE_OP_LIST(V)                  \
236   CLEAR_ACCUMULATOR_LIST(V)           \
237   CONDITIONAL_JUMPS_LIST(V)           \
238   IGNORED_BYTECODE_LIST(V)            \
239   KILL_ENVIRONMENT_LIST(V)            \
240   UNARY_OP_LIST(V)                    \
241   UNCONDITIONAL_JUMPS_LIST(V)         \
242   UNREACHABLE_BYTECODE_LIST(V)
243 
244 struct HintsImpl : public ZoneObject {
HintsImplv8::internal::compiler::HintsImpl245   explicit HintsImpl(Zone* zone) : zone_(zone) {}
246 
247   ConstantsSet constants_;
248   MapsSet maps_;
249   VirtualClosuresSet virtual_closures_;
250   VirtualContextsSet virtual_contexts_;
251   VirtualBoundFunctionsSet virtual_bound_functions_;
252 
253   Zone* const zone_;
254 };
255 
EnsureAllocated(Zone * zone,bool check_zone_equality)256 void Hints::EnsureAllocated(Zone* zone, bool check_zone_equality) {
257   if (IsAllocated()) {
258     if (check_zone_equality) CHECK_EQ(zone, impl_->zone_);
259     // ... else {zone} lives no longer than {impl_->zone_} but we have no way of
260     // checking that.
261   } else {
262     impl_ = zone->New<HintsImpl>(zone);
263   }
264   DCHECK(IsAllocated());
265 }
266 
267 struct VirtualBoundFunction {
268   Hints const bound_target;
269   HintsVector const bound_arguments;
270 
VirtualBoundFunctionv8::internal::compiler::VirtualBoundFunction271   VirtualBoundFunction(Hints const& target, const HintsVector& arguments)
272       : bound_target(target), bound_arguments(arguments) {}
273 
operator ==v8::internal::compiler::VirtualBoundFunction274   bool operator==(const VirtualBoundFunction& other) const {
275     if (bound_arguments.size() != other.bound_arguments.size()) return false;
276     if (bound_target != other.bound_target) return false;
277 
278     for (size_t i = 0; i < bound_arguments.size(); ++i) {
279       if (bound_arguments[i] != other.bound_arguments[i]) return false;
280     }
281     return true;
282   }
283 };
284 
285 // A VirtualClosure is a SharedFunctionInfo and a FeedbackVector, plus
286 // Hints about the context in which a closure will be created from them.
287 class VirtualClosure {
288  public:
289   VirtualClosure(Handle<JSFunction> function, Isolate* isolate, Zone* zone);
290 
291   VirtualClosure(Handle<SharedFunctionInfo> shared,
292                  Handle<FeedbackVector> feedback_vector,
293                  Hints const& context_hints);
294 
shared() const295   Handle<SharedFunctionInfo> shared() const { return shared_; }
feedback_vector() const296   Handle<FeedbackVector> feedback_vector() const { return feedback_vector_; }
context_hints() const297   Hints const& context_hints() const { return context_hints_; }
298 
operator ==(const VirtualClosure & other) const299   bool operator==(const VirtualClosure& other) const {
300     // A feedback vector is never used for more than one SFI.  There might,
301     // however, be two virtual closures with the same SFI and vector, but
302     // different context hints. crbug.com/1024282 has a link to a document
303     // describing why the context_hints_ might be different in that case.
304     DCHECK_IMPLIES(feedback_vector_.equals(other.feedback_vector_),
305                    shared_.equals(other.shared_));
306     return feedback_vector_.equals(other.feedback_vector_) &&
307            context_hints_ == other.context_hints_;
308   }
309 
310  private:
311   Handle<SharedFunctionInfo> const shared_;
312   Handle<FeedbackVector> const feedback_vector_;
313   Hints const context_hints_;
314 };
315 
316 // A CompilationSubject is a VirtualClosure, optionally with a matching
317 // concrete closure.
318 class CompilationSubject {
319  public:
CompilationSubject(VirtualClosure virtual_closure)320   explicit CompilationSubject(VirtualClosure virtual_closure)
321       : virtual_closure_(virtual_closure), closure_() {}
322 
323   // The zone parameter is to correctly initialize the virtual closure,
324   // which contains zone-allocated context information.
325   CompilationSubject(Handle<JSFunction> closure, Isolate* isolate, Zone* zone);
326 
virtual_closure() const327   const VirtualClosure& virtual_closure() const { return virtual_closure_; }
closure() const328   MaybeHandle<JSFunction> closure() const { return closure_; }
329 
330  private:
331   VirtualClosure const virtual_closure_;
332   MaybeHandle<JSFunction> const closure_;
333 };
334 
335 // A Callee is either a JSFunction (which may not have a feedback vector), or a
336 // VirtualClosure. Note that this is different from CompilationSubject, which
337 // always has a VirtualClosure.
338 class Callee {
339  public:
Callee(Handle<JSFunction> jsfunction)340   explicit Callee(Handle<JSFunction> jsfunction)
341       : jsfunction_(jsfunction), virtual_closure_() {}
Callee(VirtualClosure const & virtual_closure)342   explicit Callee(VirtualClosure const& virtual_closure)
343       : jsfunction_(), virtual_closure_(virtual_closure) {}
344 
shared(Isolate * isolate) const345   Handle<SharedFunctionInfo> shared(Isolate* isolate) const {
346     return virtual_closure_.has_value()
347                ? virtual_closure_->shared()
348                : handle(jsfunction_.ToHandleChecked()->shared(), isolate);
349   }
350 
HasFeedbackVector() const351   bool HasFeedbackVector() const {
352     Handle<JSFunction> function;
353     return virtual_closure_.has_value() ||
354            jsfunction_.ToHandleChecked()->has_feedback_vector();
355   }
356 
ToCompilationSubject(Isolate * isolate,Zone * zone) const357   CompilationSubject ToCompilationSubject(Isolate* isolate, Zone* zone) const {
358     CHECK(HasFeedbackVector());
359     return virtual_closure_.has_value()
360                ? CompilationSubject(*virtual_closure_)
361                : CompilationSubject(jsfunction_.ToHandleChecked(), isolate,
362                                     zone);
363   }
364 
365  private:
366   MaybeHandle<JSFunction> const jsfunction_;
367   base::Optional<VirtualClosure> const virtual_closure_;
368 };
369 
370 // If a list of arguments (hints) is shorter than the function's parameter
371 // count, this enum expresses what we know about the missing arguments.
372 enum MissingArgumentsPolicy {
373   kMissingArgumentsAreUndefined,  // ... as in the JS undefined value
374   kMissingArgumentsAreUnknown,
375 };
376 
377 // The SerializerForBackgroundCompilation makes sure that the relevant function
378 // data such as bytecode, SharedFunctionInfo and FeedbackVector, used by later
379 // optimizations in the compiler, is copied to the heap broker.
380 class SerializerForBackgroundCompilation {
381  public:
382   SerializerForBackgroundCompilation(
383       ZoneStats* zone_stats, JSHeapBroker* broker,
384       CompilationDependencies* dependencies, Handle<JSFunction> closure,
385       SerializerForBackgroundCompilationFlags flags, BailoutId osr_offset);
386   Hints Run();  // NOTE: Returns empty for an
387                 // already-serialized function.
388 
389   class Environment;
390 
391  private:
392   SerializerForBackgroundCompilation(
393       ZoneStats* zone_stats, JSHeapBroker* broker,
394       CompilationDependencies* dependencies, CompilationSubject function,
395       base::Optional<Hints> new_target, const HintsVector& arguments,
396       MissingArgumentsPolicy padding,
397       SerializerForBackgroundCompilationFlags flags, int nesting_level);
398 
399   bool BailoutOnUninitialized(ProcessedFeedback const& feedback);
400 
401   void TraverseBytecode();
402 
403 #define DECLARE_VISIT_BYTECODE(name, ...) \
404   void Visit##name(interpreter::BytecodeArrayIterator* iterator);
405   SUPPORTED_BYTECODE_LIST(DECLARE_VISIT_BYTECODE)
406 #undef DECLARE_VISIT_BYTECODE
407 
408   Hints& register_hints(interpreter::Register reg);
409 
410   // Return a vector containing the hints for the given register range (in
411   // order). Also prepare these hints for feedback backpropagation by allocating
412   // any that aren't yet allocated.
413   HintsVector PrepareArgumentsHints(interpreter::Register first, size_t count);
414 
415   // Like above except that the hints have to be given directly.
416   template <typename... MoreHints>
417   HintsVector PrepareArgumentsHints(Hints* hints, MoreHints... more);
418 
419   void ProcessCalleeForCallOrConstruct(Callee const& callee,
420                                        base::Optional<Hints> new_target,
421                                        const HintsVector& arguments,
422                                        SpeculationMode speculation_mode,
423                                        MissingArgumentsPolicy padding,
424                                        Hints* result_hints);
425   void ProcessCalleeForCallOrConstruct(Handle<Object> callee,
426                                        base::Optional<Hints> new_target,
427                                        const HintsVector& arguments,
428                                        SpeculationMode speculation_mode,
429                                        MissingArgumentsPolicy padding,
430                                        Hints* result_hints);
431   void ProcessCallOrConstruct(Hints callee, base::Optional<Hints> new_target,
432                               HintsVector* arguments, FeedbackSlot slot,
433                               MissingArgumentsPolicy padding);
434   void ProcessCallOrConstructRecursive(Hints const& callee,
435                                        base::Optional<Hints> new_target,
436                                        const HintsVector& arguments,
437                                        SpeculationMode speculation_mode,
438                                        MissingArgumentsPolicy padding,
439                                        Hints* result_hints);
440   void ProcessNewTargetForConstruct(Hints const& new_target,
441                                     Hints* result_hints);
442   void ProcessCallVarArgs(
443       ConvertReceiverMode receiver_mode, Hints const& callee,
444       interpreter::Register first_reg, int reg_count, FeedbackSlot slot,
445       MissingArgumentsPolicy padding = kMissingArgumentsAreUndefined);
446   void ProcessApiCall(Handle<SharedFunctionInfo> target,
447                       const HintsVector& arguments);
448   void ProcessReceiverMapForApiCall(FunctionTemplateInfoRef target,
449                                     Handle<Map> receiver);
450   void ProcessBuiltinCall(Handle<SharedFunctionInfo> target,
451                           base::Optional<Hints> new_target,
452                           const HintsVector& arguments,
453                           SpeculationMode speculation_mode,
454                           MissingArgumentsPolicy padding, Hints* result_hints);
455 
456   void ProcessJump(interpreter::BytecodeArrayIterator* iterator);
457 
458   void ProcessKeyedPropertyAccess(Hints* receiver, Hints const& key,
459                                   FeedbackSlot slot, AccessMode access_mode,
460                                   bool honor_bailout_on_uninitialized);
461   void ProcessNamedPropertyAccess(Hints* receiver, NameRef const& name,
462                                   FeedbackSlot slot, AccessMode access_mode);
463   void ProcessNamedSuperPropertyAccess(Hints* receiver, NameRef const& name,
464                                        FeedbackSlot slot,
465                                        AccessMode access_mode);
466   void ProcessNamedAccess(Hints* receiver, NamedAccessFeedback const& feedback,
467                           AccessMode access_mode, Hints* result_hints);
468   void ProcessNamedSuperAccess(Hints* receiver,
469                                NamedAccessFeedback const& feedback,
470                                AccessMode access_mode, Hints* result_hints);
471   void ProcessElementAccess(Hints const& receiver, Hints const& key,
472                             ElementAccessFeedback const& feedback,
473                             AccessMode access_mode);
474   void ProcessMinimorphicPropertyAccess(
475       MinimorphicLoadPropertyAccessFeedback const& feedback,
476       FeedbackSource const& source);
477 
478   void ProcessModuleVariableAccess(
479       interpreter::BytecodeArrayIterator* iterator);
480 
481   void ProcessHintsForObjectCreate(Hints const& prototype);
482   void ProcessMapHintsForPromises(Hints const& receiver_hints);
483   void ProcessHintsForPromiseResolve(Hints const& resolution_hints);
484   void ProcessHintsForHasInPrototypeChain(Hints const& instance_hints);
485   void ProcessHintsForRegExpTest(Hints const& regexp_hints);
486   PropertyAccessInfo ProcessMapForRegExpTest(MapRef map);
487   void ProcessHintsForFunctionBind(Hints const& receiver_hints);
488   void ProcessHintsForObjectGetPrototype(Hints const& object_hints);
489   void ProcessConstantForOrdinaryHasInstance(HeapObjectRef const& constructor,
490                                              bool* walk_prototypes);
491   void ProcessConstantForInstanceOf(ObjectRef const& constant,
492                                     bool* walk_prototypes);
493   void ProcessHintsForOrdinaryHasInstance(Hints const& constructor_hints,
494                                           Hints const& instance_hints);
495 
496   void ProcessGlobalAccess(FeedbackSlot slot, bool is_load);
497 
498   void ProcessCompareOperation(FeedbackSlot slot);
499   void ProcessForIn(FeedbackSlot slot);
500   void ProcessUnaryOrBinaryOperation(FeedbackSlot slot,
501                                      bool honor_bailout_on_uninitialized);
502 
503   PropertyAccessInfo ProcessMapForNamedPropertyAccess(
504       Hints* receiver, base::Optional<MapRef> receiver_map,
505       MapRef lookup_start_object_map, NameRef const& name,
506       AccessMode access_mode, base::Optional<JSObjectRef> concrete_receiver,
507       Hints* result_hints);
508 
509   void ProcessCreateContext(interpreter::BytecodeArrayIterator* iterator,
510                             int scopeinfo_operand_index);
511 
512   enum ContextProcessingMode {
513     kIgnoreSlot,
514     kSerializeSlot,
515   };
516 
517   void ProcessContextAccess(Hints const& context_hints, int slot, int depth,
518                             ContextProcessingMode mode,
519                             Hints* result_hints = nullptr);
520   void ProcessImmutableLoad(ContextRef const& context, int slot,
521                             ContextProcessingMode mode,
522                             Hints* new_accumulator_hints);
523   void ProcessLdaLookupGlobalSlot(interpreter::BytecodeArrayIterator* iterator);
524   void ProcessLdaLookupContextSlot(
525       interpreter::BytecodeArrayIterator* iterator);
526 
527   // Performs extension lookups for [0, depth) like
528   // BytecodeGraphBuilder::CheckContextExtensions().
529   void ProcessCheckContextExtensions(int depth);
530 
531   Hints RunChildSerializer(CompilationSubject function,
532                            base::Optional<Hints> new_target,
533                            const HintsVector& arguments,
534                            MissingArgumentsPolicy padding);
535 
536   // When (forward-)branching bytecodes are encountered, e.g. a conditional
537   // jump, we call ContributeToJumpTargetEnvironment to "remember" the current
538   // environment, associated with the jump target offset. When serialization
539   // eventually reaches that offset, we call IncorporateJumpTargetEnvironment to
540   // merge that environment back into whatever is the current environment then.
541   // Note: Since there may be multiple jumps to the same target,
542   // ContributeToJumpTargetEnvironment may actually do a merge as well.
543   void ContributeToJumpTargetEnvironment(int target_offset);
544   void IncorporateJumpTargetEnvironment(int target_offset);
545 
function() const546   VirtualClosure function() const { return function_; }
547 
return_value_hints()548   Hints& return_value_hints() { return return_value_hints_; }
549 
550   Handle<FeedbackVector> feedback_vector() const;
551   Handle<BytecodeArray> bytecode_array() const;
552   BytecodeAnalysis const& GetBytecodeAnalysis(
553       SerializationPolicy policy = SerializationPolicy::kAssumeSerialized);
554 
broker() const555   JSHeapBroker* broker() const { return broker_; }
dependencies() const556   CompilationDependencies* dependencies() const { return dependencies_; }
zone()557   Zone* zone() { return zone_scope_.zone(); }
environment() const558   Environment* environment() const { return environment_; }
flags() const559   SerializerForBackgroundCompilationFlags flags() const { return flags_; }
osr_offset() const560   BailoutId osr_offset() const { return osr_offset_; }
561 
562   JSHeapBroker* const broker_;
563   CompilationDependencies* const dependencies_;
564   ZoneStats::Scope zone_scope_;
565   SerializerForBackgroundCompilationFlags const flags_;
566   // Instead of storing the virtual_closure here, we could extract it from the
567   // {closure_hints_} but that would be cumbersome.
568   VirtualClosure const function_;
569   BailoutId const osr_offset_;
570   ZoneUnorderedMap<int, Environment*> jump_target_environments_;
571   Environment* const environment_;
572   HintsVector const arguments_;
573   Hints return_value_hints_;
574   Hints closure_hints_;
575 
576   int nesting_level_ = 0;
577 };
578 
RunSerializerForBackgroundCompilation(ZoneStats * zone_stats,JSHeapBroker * broker,CompilationDependencies * dependencies,Handle<JSFunction> closure,SerializerForBackgroundCompilationFlags flags,BailoutId osr_offset)579 void RunSerializerForBackgroundCompilation(
580     ZoneStats* zone_stats, JSHeapBroker* broker,
581     CompilationDependencies* dependencies, Handle<JSFunction> closure,
582     SerializerForBackgroundCompilationFlags flags, BailoutId osr_offset) {
583   SerializerForBackgroundCompilation serializer(
584       zone_stats, broker, dependencies, closure, flags, osr_offset);
585   serializer.Run();
586 }
587 
588 using BytecodeArrayIterator = interpreter::BytecodeArrayIterator;
589 
VirtualClosure(Handle<SharedFunctionInfo> shared,Handle<FeedbackVector> feedback_vector,Hints const & context_hints)590 VirtualClosure::VirtualClosure(Handle<SharedFunctionInfo> shared,
591                                Handle<FeedbackVector> feedback_vector,
592                                Hints const& context_hints)
593     : shared_(shared),
594       feedback_vector_(feedback_vector),
595       context_hints_(context_hints) {
596   // The checked invariant rules out recursion and thus avoids complexity.
597   CHECK(context_hints_.virtual_closures().IsEmpty());
598 }
599 
VirtualClosure(Handle<JSFunction> function,Isolate * isolate,Zone * zone)600 VirtualClosure::VirtualClosure(Handle<JSFunction> function, Isolate* isolate,
601                                Zone* zone)
602     : shared_(handle(function->shared(), isolate)),
603       feedback_vector_(function->feedback_vector(), isolate),
604       context_hints_(
605           Hints::SingleConstant(handle(function->context(), isolate), zone)) {
606   // The checked invariant rules out recursion and thus avoids complexity.
607   CHECK(context_hints_.virtual_closures().IsEmpty());
608 }
609 
CompilationSubject(Handle<JSFunction> closure,Isolate * isolate,Zone * zone)610 CompilationSubject::CompilationSubject(Handle<JSFunction> closure,
611                                        Isolate* isolate, Zone* zone)
612     : virtual_closure_(closure, isolate, zone), closure_(closure) {
613   CHECK(closure->has_feedback_vector());
614 }
615 
Copy(Zone * zone) const616 Hints Hints::Copy(Zone* zone) const {
617   if (!IsAllocated()) return *this;
618   Hints result;
619   result.EnsureAllocated(zone);
620   result.impl_->constants_ = impl_->constants_;
621   result.impl_->maps_ = impl_->maps_;
622   result.impl_->virtual_contexts_ = impl_->virtual_contexts_;
623   result.impl_->virtual_closures_ = impl_->virtual_closures_;
624   result.impl_->virtual_bound_functions_ = impl_->virtual_bound_functions_;
625   return result;
626 }
627 
operator ==(Hints const & other) const628 bool Hints::operator==(Hints const& other) const {
629   if (impl_ == other.impl_) return true;
630   if (IsEmpty() && other.IsEmpty()) return true;
631   return IsAllocated() && other.IsAllocated() &&
632          constants() == other.constants() &&
633          virtual_closures() == other.virtual_closures() &&
634          maps() == other.maps() &&
635          virtual_contexts() == other.virtual_contexts() &&
636          virtual_bound_functions() == other.virtual_bound_functions();
637 }
638 
operator !=(Hints const & other) const639 bool Hints::operator!=(Hints const& other) const { return !(*this == other); }
640 
641 #ifdef ENABLE_SLOW_DCHECKS
Includes(Hints const & other) const642 bool Hints::Includes(Hints const& other) const {
643   if (impl_ == other.impl_ || other.IsEmpty()) return true;
644   return IsAllocated() && constants().Includes(other.constants()) &&
645          virtual_closures().Includes(other.virtual_closures()) &&
646          maps().Includes(other.maps());
647 }
648 #endif
649 
SingleConstant(Handle<Object> constant,Zone * zone)650 Hints Hints::SingleConstant(Handle<Object> constant, Zone* zone) {
651   Hints result;
652   result.AddConstant(constant, zone, nullptr);
653   return result;
654 }
655 
SingleMap(Handle<Map> map,Zone * zone)656 Hints Hints::SingleMap(Handle<Map> map, Zone* zone) {
657   Hints result;
658   result.AddMap(map, zone, nullptr);
659   return result;
660 }
661 
constants() const662 ConstantsSet Hints::constants() const {
663   return IsAllocated() ? impl_->constants_ : ConstantsSet();
664 }
665 
maps() const666 MapsSet Hints::maps() const { return IsAllocated() ? impl_->maps_ : MapsSet(); }
667 
virtual_closures() const668 VirtualClosuresSet Hints::virtual_closures() const {
669   return IsAllocated() ? impl_->virtual_closures_ : VirtualClosuresSet();
670 }
671 
virtual_contexts() const672 VirtualContextsSet Hints::virtual_contexts() const {
673   return IsAllocated() ? impl_->virtual_contexts_ : VirtualContextsSet();
674 }
675 
virtual_bound_functions() const676 VirtualBoundFunctionsSet Hints::virtual_bound_functions() const {
677   return IsAllocated() ? impl_->virtual_bound_functions_
678                        : VirtualBoundFunctionsSet();
679 }
680 
AddVirtualContext(VirtualContext const & virtual_context,Zone * zone,JSHeapBroker * broker)681 void Hints::AddVirtualContext(VirtualContext const& virtual_context, Zone* zone,
682                               JSHeapBroker* broker) {
683   EnsureAllocated(zone);
684   if (impl_->virtual_contexts_.Size() >= kMaxHintsSize) {
685     TRACE_BROKER_MISSING(broker,
686                          "opportunity - limit for virtual contexts reached.");
687     return;
688   }
689   impl_->virtual_contexts_.Add(virtual_context, impl_->zone_);
690 }
691 
AddConstant(Handle<Object> constant,Zone * zone,JSHeapBroker * broker)692 void Hints::AddConstant(Handle<Object> constant, Zone* zone,
693                         JSHeapBroker* broker) {
694   EnsureAllocated(zone);
695   if (impl_->constants_.Size() >= kMaxHintsSize) {
696     TRACE_BROKER_MISSING(broker, "opportunity - limit for constants reached.");
697     return;
698   }
699   impl_->constants_.Add(constant, impl_->zone_);
700 }
701 
AddMap(Handle<Map> map,Zone * zone,JSHeapBroker * broker,bool check_zone_equality)702 void Hints::AddMap(Handle<Map> map, Zone* zone, JSHeapBroker* broker,
703                    bool check_zone_equality) {
704   EnsureAllocated(zone, check_zone_equality);
705   if (impl_->maps_.Size() >= kMaxHintsSize) {
706     TRACE_BROKER_MISSING(broker, "opportunity - limit for maps reached.");
707     return;
708   }
709   impl_->maps_.Add(map, impl_->zone_);
710 }
711 
AddVirtualClosure(VirtualClosure const & virtual_closure,Zone * zone,JSHeapBroker * broker)712 void Hints::AddVirtualClosure(VirtualClosure const& virtual_closure, Zone* zone,
713                               JSHeapBroker* broker) {
714   EnsureAllocated(zone);
715   if (impl_->virtual_closures_.Size() >= kMaxHintsSize) {
716     TRACE_BROKER_MISSING(broker,
717                          "opportunity - limit for virtual closures reached.");
718     return;
719   }
720   impl_->virtual_closures_.Add(virtual_closure, impl_->zone_);
721 }
722 
AddVirtualBoundFunction(VirtualBoundFunction const & bound_function,Zone * zone,JSHeapBroker * broker)723 void Hints::AddVirtualBoundFunction(VirtualBoundFunction const& bound_function,
724                                     Zone* zone, JSHeapBroker* broker) {
725   EnsureAllocated(zone);
726   if (impl_->virtual_bound_functions_.Size() >= kMaxHintsSize) {
727     TRACE_BROKER_MISSING(
728         broker, "opportunity - limit for virtual bound functions reached.");
729     return;
730   }
731   // TODO(mslekova): Consider filtering the hints in the added bound function,
732   // for example: a) Remove any non-JS(Bound)Function constants, b) Truncate the
733   // argument vector the formal parameter count.
734   impl_->virtual_bound_functions_.Add(bound_function, impl_->zone_);
735 }
736 
Add(Hints const & other,Zone * zone,JSHeapBroker * broker)737 void Hints::Add(Hints const& other, Zone* zone, JSHeapBroker* broker) {
738   if (impl_ == other.impl_ || other.IsEmpty()) return;
739   EnsureAllocated(zone);
740   if (!Union(other)) {
741     TRACE_BROKER_MISSING(broker, "opportunity - hints limit reached.");
742   }
743 }
744 
CopyToParentZone(Zone * zone,JSHeapBroker * broker) const745 Hints Hints::CopyToParentZone(Zone* zone, JSHeapBroker* broker) const {
746   if (!IsAllocated()) return *this;
747 
748   Hints result;
749 
750   for (auto const& x : constants()) result.AddConstant(x, zone, broker);
751   for (auto const& x : maps()) result.AddMap(x, zone, broker);
752   for (auto const& x : virtual_contexts())
753     result.AddVirtualContext(x, zone, broker);
754 
755   // Adding hints from a child serializer run means copying data out from
756   // a zone that's being destroyed. VirtualClosures and VirtualBoundFunction
757   // have zone allocated data, so we've got to make a deep copy to eliminate
758   // traces of the dying zone.
759   for (auto const& x : virtual_closures()) {
760     VirtualClosure new_virtual_closure(
761         x.shared(), x.feedback_vector(),
762         x.context_hints().CopyToParentZone(zone, broker));
763     result.AddVirtualClosure(new_virtual_closure, zone, broker);
764   }
765   for (auto const& x : virtual_bound_functions()) {
766     HintsVector new_arguments_hints(zone);
767     for (auto hint : x.bound_arguments) {
768       new_arguments_hints.push_back(hint.CopyToParentZone(zone, broker));
769     }
770     VirtualBoundFunction new_bound_function(
771         x.bound_target.CopyToParentZone(zone, broker), new_arguments_hints);
772     result.AddVirtualBoundFunction(new_bound_function, zone, broker);
773   }
774 
775   return result;
776 }
777 
IsEmpty() const778 bool Hints::IsEmpty() const {
779   if (!IsAllocated()) return true;
780   return constants().IsEmpty() && maps().IsEmpty() &&
781          virtual_closures().IsEmpty() && virtual_contexts().IsEmpty() &&
782          virtual_bound_functions().IsEmpty();
783 }
784 
operator <<(std::ostream & out,const VirtualContext & virtual_context)785 std::ostream& operator<<(std::ostream& out,
786                          const VirtualContext& virtual_context) {
787   out << "Distance " << virtual_context.distance << " from "
788       << Brief(*virtual_context.context) << std::endl;
789   return out;
790 }
791 
792 std::ostream& operator<<(std::ostream& out, const Hints& hints);
793 
operator <<(std::ostream & out,const VirtualClosure & virtual_closure)794 std::ostream& operator<<(std::ostream& out,
795                          const VirtualClosure& virtual_closure) {
796   out << Brief(*virtual_closure.shared()) << std::endl;
797   out << Brief(*virtual_closure.feedback_vector()) << std::endl;
798   !virtual_closure.context_hints().IsEmpty() &&
799       out << virtual_closure.context_hints() << "):" << std::endl;
800   return out;
801 }
802 
operator <<(std::ostream & out,const VirtualBoundFunction & virtual_bound_function)803 std::ostream& operator<<(std::ostream& out,
804                          const VirtualBoundFunction& virtual_bound_function) {
805   out << std::endl << "    Target: " << virtual_bound_function.bound_target;
806   out << "    Arguments:" << std::endl;
807   for (auto hint : virtual_bound_function.bound_arguments) {
808     out << "    " << hint;
809   }
810   return out;
811 }
812 
operator <<(std::ostream & out,const Hints & hints)813 std::ostream& operator<<(std::ostream& out, const Hints& hints) {
814   out << "(impl_ = " << hints.impl_ << ")\n";
815   for (Handle<Object> constant : hints.constants()) {
816     out << "  constant " << Brief(*constant) << std::endl;
817   }
818   for (Handle<Map> map : hints.maps()) {
819     out << "  map " << Brief(*map) << std::endl;
820   }
821   for (VirtualClosure const& virtual_closure : hints.virtual_closures()) {
822     out << "  virtual closure " << virtual_closure << std::endl;
823   }
824   for (VirtualContext const& virtual_context : hints.virtual_contexts()) {
825     out << "  virtual context " << virtual_context << std::endl;
826   }
827   for (VirtualBoundFunction const& virtual_bound_function :
828        hints.virtual_bound_functions()) {
829     out << "  virtual bound function " << virtual_bound_function << std::endl;
830   }
831   return out;
832 }
833 
Reset(Hints * other,Zone * zone)834 void Hints::Reset(Hints* other, Zone* zone) {
835   other->EnsureShareable(zone);
836   *this = *other;
837   DCHECK(IsAllocated());
838 }
839 
840 class SerializerForBackgroundCompilation::Environment : public ZoneObject {
841  public:
842   Environment(Zone* zone, CompilationSubject function);
843   Environment(Zone* zone, Isolate* isolate, CompilationSubject function,
844               base::Optional<Hints> new_target, const HintsVector& arguments,
845               MissingArgumentsPolicy padding);
846 
IsDead() const847   bool IsDead() const { return !alive_; }
848 
Kill()849   void Kill() {
850     DCHECK(!IsDead());
851     alive_ = false;
852     DCHECK(IsDead());
853   }
854 
Resurrect()855   void Resurrect() {
856     DCHECK(IsDead());
857     alive_ = true;
858     DCHECK(!IsDead());
859   }
860 
861   // Merge {other} into {this} environment (leaving {other} unmodified).
862   void Merge(Environment* other, Zone* zone, JSHeapBroker* broker);
863 
current_context_hints() const864   Hints const& current_context_hints() const { return current_context_hints_; }
accumulator_hints() const865   Hints const& accumulator_hints() const { return accumulator_hints_; }
866 
current_context_hints()867   Hints& current_context_hints() { return current_context_hints_; }
accumulator_hints()868   Hints& accumulator_hints() { return accumulator_hints_; }
869   Hints& register_hints(interpreter::Register reg);
870 
871  private:
872   friend std::ostream& operator<<(std::ostream& out, const Environment& env);
873 
874   Hints current_context_hints_;
875   Hints accumulator_hints_;
876 
877   HintsVector parameters_hints_;  // First parameter is the receiver.
878   HintsVector locals_hints_;
879 
880   bool alive_ = true;
881 };
882 
Environment(Zone * zone,CompilationSubject function)883 SerializerForBackgroundCompilation::Environment::Environment(
884     Zone* zone, CompilationSubject function)
885     : parameters_hints_(function.virtual_closure()
886                             .shared()
887                             ->GetBytecodeArray()
888                             .parameter_count(),
889                         Hints(), zone),
890       locals_hints_(function.virtual_closure()
891                         .shared()
892                         ->GetBytecodeArray()
893                         .register_count(),
894                     Hints(), zone) {
895   // Consume the virtual_closure's context hint information.
896   current_context_hints_ = function.virtual_closure().context_hints();
897 }
898 
Environment(Zone * zone,Isolate * isolate,CompilationSubject function,base::Optional<Hints> new_target,const HintsVector & arguments,MissingArgumentsPolicy padding)899 SerializerForBackgroundCompilation::Environment::Environment(
900     Zone* zone, Isolate* isolate, CompilationSubject function,
901     base::Optional<Hints> new_target, const HintsVector& arguments,
902     MissingArgumentsPolicy padding)
903     : Environment(zone, function) {
904   // Set the hints for the actually passed arguments, at most up to
905   // the parameter_count.
906   for (size_t i = 0; i < std::min(arguments.size(), parameters_hints_.size());
907        ++i) {
908     parameters_hints_[i] = arguments[i];
909   }
910 
911   if (padding == kMissingArgumentsAreUndefined) {
912     Hints const undefined_hint =
913         Hints::SingleConstant(isolate->factory()->undefined_value(), zone);
914     for (size_t i = arguments.size(); i < parameters_hints_.size(); ++i) {
915       parameters_hints_[i] = undefined_hint;
916     }
917   } else {
918     DCHECK_EQ(padding, kMissingArgumentsAreUnknown);
919   }
920 
921   // Set hints for new_target.
922   interpreter::Register new_target_reg =
923       function.virtual_closure()
924           .shared()
925           ->GetBytecodeArray()
926           .incoming_new_target_or_generator_register();
927   if (new_target_reg.is_valid()) {
928     Hints& hints = register_hints(new_target_reg);
929     CHECK(hints.IsEmpty());
930     if (new_target.has_value()) hints = *new_target;
931   }
932 }
933 
register_hints(interpreter::Register reg)934 Hints& SerializerForBackgroundCompilation::register_hints(
935     interpreter::Register reg) {
936   if (reg.is_function_closure()) return closure_hints_;
937   return environment()->register_hints(reg);
938 }
939 
register_hints(interpreter::Register reg)940 Hints& SerializerForBackgroundCompilation::Environment::register_hints(
941     interpreter::Register reg) {
942   if (reg.is_current_context()) return current_context_hints_;
943   if (reg.is_parameter()) {
944     return parameters_hints_[reg.ToParameterIndex(
945         static_cast<int>(parameters_hints_.size()))];
946   }
947   DCHECK(!reg.is_function_closure());
948   CHECK_LT(reg.index(), locals_hints_.size());
949   return locals_hints_[reg.index()];
950 }
951 
Merge(Environment * other,Zone * zone,JSHeapBroker * broker)952 void SerializerForBackgroundCompilation::Environment::Merge(
953     Environment* other, Zone* zone, JSHeapBroker* broker) {
954   // {other} is guaranteed to have the same layout because it comes from an
955   // earlier bytecode in the same function.
956   DCHECK_EQ(parameters_hints_.size(), other->parameters_hints_.size());
957   DCHECK_EQ(locals_hints_.size(), other->locals_hints_.size());
958 
959   if (IsDead()) {
960     parameters_hints_ = other->parameters_hints_;
961     locals_hints_ = other->locals_hints_;
962     current_context_hints_ = other->current_context_hints_;
963     accumulator_hints_ = other->accumulator_hints_;
964     Resurrect();
965   } else {
966     for (size_t i = 0; i < parameters_hints_.size(); ++i) {
967       parameters_hints_[i].Merge(other->parameters_hints_[i], zone, broker);
968     }
969     for (size_t i = 0; i < locals_hints_.size(); ++i) {
970       locals_hints_[i].Merge(other->locals_hints_[i], zone, broker);
971     }
972     current_context_hints_.Merge(other->current_context_hints_, zone, broker);
973     accumulator_hints_.Merge(other->accumulator_hints_, zone, broker);
974   }
975 
976   CHECK(!IsDead());
977 }
978 
Union(Hints const & other)979 bool Hints::Union(Hints const& other) {
980   CHECK(IsAllocated());
981   if (impl_->constants_.Size() + other.constants().Size() > kMaxHintsSize ||
982       impl_->maps_.Size() + other.maps().Size() > kMaxHintsSize ||
983       impl_->virtual_closures_.Size() + other.virtual_closures().Size() >
984           kMaxHintsSize ||
985       impl_->virtual_contexts_.Size() + other.virtual_contexts().Size() >
986           kMaxHintsSize ||
987       impl_->virtual_bound_functions_.Size() +
988               other.virtual_bound_functions().Size() >
989           kMaxHintsSize) {
990     return false;
991   }
992   Zone* zone = impl_->zone_;
993   impl_->constants_.Union(other.constants(), zone);
994   impl_->maps_.Union(other.maps(), zone);
995   impl_->virtual_closures_.Union(other.virtual_closures(), zone);
996   impl_->virtual_contexts_.Union(other.virtual_contexts(), zone);
997   impl_->virtual_bound_functions_.Union(other.virtual_bound_functions(), zone);
998   return true;
999 }
1000 
Merge(Hints const & other,Zone * zone,JSHeapBroker * broker)1001 void Hints::Merge(Hints const& other, Zone* zone, JSHeapBroker* broker) {
1002   if (impl_ == other.impl_) {
1003     return;
1004   }
1005   if (!IsAllocated()) {
1006     *this = other.Copy(zone);
1007     DCHECK(IsAllocated());
1008     return;
1009   }
1010   *this = this->Copy(zone);
1011   if (!Union(other)) {
1012     TRACE_BROKER_MISSING(broker, "opportunity - hints limit reached.");
1013   }
1014   DCHECK(IsAllocated());
1015 }
1016 
operator <<(std::ostream & out,const SerializerForBackgroundCompilation::Environment & env)1017 std::ostream& operator<<(
1018     std::ostream& out,
1019     const SerializerForBackgroundCompilation::Environment& env) {
1020   std::ostringstream output_stream;
1021 
1022   if (env.IsDead()) {
1023     output_stream << "dead\n";
1024   } else {
1025     output_stream << "alive\n";
1026     for (size_t i = 0; i < env.parameters_hints_.size(); ++i) {
1027       Hints const& hints = env.parameters_hints_[i];
1028       if (!hints.IsEmpty()) {
1029         if (i == 0) {
1030           output_stream << "Hints for <this>: ";
1031         } else {
1032           output_stream << "Hints for a" << i - 1 << ": ";
1033         }
1034         output_stream << hints;
1035       }
1036     }
1037     for (size_t i = 0; i < env.locals_hints_.size(); ++i) {
1038       Hints const& hints = env.locals_hints_[i];
1039       if (!hints.IsEmpty()) {
1040         output_stream << "Hints for r" << i << ": " << hints;
1041       }
1042     }
1043   }
1044 
1045   if (!env.current_context_hints().IsEmpty()) {
1046     output_stream << "Hints for <context>: " << env.current_context_hints();
1047   }
1048   if (!env.accumulator_hints().IsEmpty()) {
1049     output_stream << "Hints for <accumulator>: " << env.accumulator_hints();
1050   }
1051 
1052   out << output_stream.str();
1053   return out;
1054 }
1055 
SerializerForBackgroundCompilation(ZoneStats * zone_stats,JSHeapBroker * broker,CompilationDependencies * dependencies,Handle<JSFunction> closure,SerializerForBackgroundCompilationFlags flags,BailoutId osr_offset)1056 SerializerForBackgroundCompilation::SerializerForBackgroundCompilation(
1057     ZoneStats* zone_stats, JSHeapBroker* broker,
1058     CompilationDependencies* dependencies, Handle<JSFunction> closure,
1059     SerializerForBackgroundCompilationFlags flags, BailoutId osr_offset)
1060     : broker_(broker),
1061       dependencies_(dependencies),
1062       zone_scope_(zone_stats, ZONE_NAME),
1063       flags_(flags),
1064       function_(closure, broker->isolate(), zone()),
1065       osr_offset_(osr_offset),
1066       jump_target_environments_(zone()),
1067       environment_(zone()->New<Environment>(
1068           zone(), CompilationSubject(closure, broker_->isolate(), zone()))),
1069       arguments_(zone()) {
1070   closure_hints_.AddConstant(closure, zone(), broker_);
1071   JSFunctionRef(broker, closure).Serialize();
1072 
1073   TRACE_BROKER(broker_, "Hints for <closure>: " << closure_hints_);
1074   TRACE_BROKER(broker_, "Initial environment:\n" << *environment_);
1075 }
1076 
SerializerForBackgroundCompilation(ZoneStats * zone_stats,JSHeapBroker * broker,CompilationDependencies * dependencies,CompilationSubject function,base::Optional<Hints> new_target,const HintsVector & arguments,MissingArgumentsPolicy padding,SerializerForBackgroundCompilationFlags flags,int nesting_level)1077 SerializerForBackgroundCompilation::SerializerForBackgroundCompilation(
1078     ZoneStats* zone_stats, JSHeapBroker* broker,
1079     CompilationDependencies* dependencies, CompilationSubject function,
1080     base::Optional<Hints> new_target, const HintsVector& arguments,
1081     MissingArgumentsPolicy padding,
1082     SerializerForBackgroundCompilationFlags flags, int nesting_level)
1083     : broker_(broker),
1084       dependencies_(dependencies),
1085       zone_scope_(zone_stats, ZONE_NAME),
1086       flags_(flags),
1087       function_(function.virtual_closure()),
1088       osr_offset_(BailoutId::None()),
1089       jump_target_environments_(zone()),
1090       environment_(zone()->New<Environment>(zone(), broker_->isolate(),
1091                                             function, new_target, arguments,
1092                                             padding)),
1093       arguments_(arguments),
1094       nesting_level_(nesting_level) {
1095   Handle<JSFunction> closure;
1096   if (function.closure().ToHandle(&closure)) {
1097     closure_hints_.AddConstant(closure, zone(), broker);
1098     JSFunctionRef(broker, closure).Serialize();
1099   } else {
1100     closure_hints_.AddVirtualClosure(function.virtual_closure(), zone(),
1101                                      broker);
1102   }
1103 
1104   TRACE_BROKER(broker_, "Hints for <closure>: " << closure_hints_);
1105   TRACE_BROKER(broker_, "Initial environment:\n" << *environment_);
1106 }
1107 
BailoutOnUninitialized(ProcessedFeedback const & feedback)1108 bool SerializerForBackgroundCompilation::BailoutOnUninitialized(
1109     ProcessedFeedback const& feedback) {
1110   DCHECK(!environment()->IsDead());
1111   if (!(flags() &
1112         SerializerForBackgroundCompilationFlag::kBailoutOnUninitialized)) {
1113     return false;
1114   }
1115   if (!osr_offset().IsNone()) {
1116     // Exclude OSR from this optimization because we might end up skipping the
1117     // OSR entry point. TODO(neis): Support OSR?
1118     return false;
1119   }
1120   if (broker()->is_turboprop() &&
1121       feedback.slot_kind() == FeedbackSlotKind::kCall) {
1122     return false;
1123   }
1124   if (feedback.IsInsufficient()) {
1125     environment()->Kill();
1126     return true;
1127   }
1128   return false;
1129 }
1130 
Run()1131 Hints SerializerForBackgroundCompilation::Run() {
1132   TraceScope tracer(broker(), this, "SerializerForBackgroundCompilation::Run");
1133   if (nesting_level_ >= FLAG_max_serializer_nesting) {
1134     TRACE_BROKER_MISSING(
1135         broker(),
1136         "opportunity - Reached max nesting level for "
1137         "SerializerForBackgroundCompilation::Run, bailing out.\n");
1138     return Hints();
1139   }
1140 
1141   TRACE_BROKER_MEMORY(broker(), "[serializer start] Broker zone usage: "
1142                                     << broker()->zone()->allocation_size());
1143   SharedFunctionInfoRef shared(broker(), function().shared());
1144   FeedbackVectorRef feedback_vector_ref(broker(), feedback_vector());
1145   if (!broker()->ShouldBeSerializedForCompilation(shared, feedback_vector_ref,
1146                                                   arguments_)) {
1147     TRACE_BROKER(broker(),
1148                  "opportunity - Already ran serializer for SharedFunctionInfo "
1149                      << Brief(*shared.object()) << ", bailing out.\n");
1150     return Hints();
1151   }
1152 
1153   {
1154     HintsVector arguments_copy_in_broker_zone(broker()->zone());
1155     for (auto const& hints : arguments_) {
1156       arguments_copy_in_broker_zone.push_back(
1157           hints.CopyToParentZone(broker()->zone(), broker()));
1158     }
1159     broker()->SetSerializedForCompilation(shared, feedback_vector_ref,
1160                                           arguments_copy_in_broker_zone);
1161   }
1162 
1163   // We eagerly call the {EnsureSourcePositionsAvailable} for all serialized
1164   // SFIs while still on the main thread. Source positions will later be used
1165   // by JSInliner::ReduceJSCall.
1166   if (flags() &
1167       SerializerForBackgroundCompilationFlag::kCollectSourcePositions) {
1168     SharedFunctionInfo::EnsureSourcePositionsAvailable(broker()->isolate(),
1169                                                        shared.object());
1170   }
1171 
1172   feedback_vector_ref.Serialize();
1173   TraverseBytecode();
1174 
1175   if (return_value_hints().IsEmpty()) {
1176     TRACE_BROKER(broker(), "Return value hints: none");
1177   } else {
1178     TRACE_BROKER(broker(), "Return value hints: " << return_value_hints());
1179   }
1180   TRACE_BROKER_MEMORY(broker(), "[serializer end] Broker zone usage: "
1181                                     << broker()->zone()->allocation_size());
1182   return return_value_hints();
1183 }
1184 
1185 class HandlerRangeMatcher {
1186  public:
HandlerRangeMatcher(BytecodeArrayIterator const & bytecode_iterator,Handle<BytecodeArray> bytecode_array)1187   HandlerRangeMatcher(BytecodeArrayIterator const& bytecode_iterator,
1188                       Handle<BytecodeArray> bytecode_array)
1189       : bytecode_iterator_(bytecode_iterator) {
1190     HandlerTable table(*bytecode_array);
1191     for (int i = 0, n = table.NumberOfRangeEntries(); i < n; ++i) {
1192       ranges_.insert({table.GetRangeStart(i), table.GetRangeEnd(i),
1193                       table.GetRangeHandler(i)});
1194     }
1195     ranges_iterator_ = ranges_.cbegin();
1196   }
1197 
1198   using OffsetReporter = std::function<void(int handler_offset)>;
1199 
HandlerOffsetForCurrentPosition(const OffsetReporter & offset_reporter)1200   void HandlerOffsetForCurrentPosition(const OffsetReporter& offset_reporter) {
1201     CHECK(!bytecode_iterator_.done());
1202     const int current_offset = bytecode_iterator_.current_offset();
1203 
1204     // Remove outdated try ranges from the stack.
1205     while (!stack_.empty()) {
1206       const int end = stack_.top().end;
1207       if (end < current_offset) {
1208         stack_.pop();
1209       } else {
1210         break;
1211       }
1212     }
1213 
1214     // Advance the iterator and maintain the stack.
1215     while (ranges_iterator_ != ranges_.cend() &&
1216            ranges_iterator_->start <= current_offset) {
1217       if (ranges_iterator_->end >= current_offset) {
1218         stack_.push(*ranges_iterator_);
1219         if (ranges_iterator_->start == current_offset) {
1220           offset_reporter(ranges_iterator_->handler);
1221         }
1222       }
1223       ranges_iterator_++;
1224     }
1225 
1226     if (!stack_.empty() && stack_.top().start < current_offset) {
1227       offset_reporter(stack_.top().handler);
1228     }
1229   }
1230 
1231  private:
1232   BytecodeArrayIterator const& bytecode_iterator_;
1233 
1234   struct Range {
1235     int start;
1236     int end;
1237     int handler;
operator <(const Range & a,const Range & b)1238     friend bool operator<(const Range& a, const Range& b) {
1239       if (a.start < b.start) return true;
1240       if (a.start == b.start) {
1241         if (a.end < b.end) return true;
1242         CHECK_GT(a.end, b.end);
1243       }
1244       return false;
1245     }
1246   };
1247   std::set<Range> ranges_;
1248   std::set<Range>::const_iterator ranges_iterator_;
1249   std::stack<Range> stack_;
1250 };
1251 
feedback_vector() const1252 Handle<FeedbackVector> SerializerForBackgroundCompilation::feedback_vector()
1253     const {
1254   return function().feedback_vector();
1255 }
1256 
bytecode_array() const1257 Handle<BytecodeArray> SerializerForBackgroundCompilation::bytecode_array()
1258     const {
1259   return handle(function().shared()->GetBytecodeArray(), broker()->isolate());
1260 }
1261 
GetBytecodeAnalysis(SerializationPolicy policy)1262 BytecodeAnalysis const& SerializerForBackgroundCompilation::GetBytecodeAnalysis(
1263     SerializationPolicy policy) {
1264   return broker()->GetBytecodeAnalysis(
1265       bytecode_array(), osr_offset(),
1266       flags() &
1267           SerializerForBackgroundCompilationFlag::kAnalyzeEnvironmentLiveness,
1268       policy);
1269 }
1270 
TraverseBytecode()1271 void SerializerForBackgroundCompilation::TraverseBytecode() {
1272   BytecodeAnalysis const& bytecode_analysis =
1273       GetBytecodeAnalysis(SerializationPolicy::kSerializeIfNeeded);
1274   BytecodeArrayRef(broker(), bytecode_array()).SerializeForCompilation();
1275 
1276   BytecodeArrayIterator iterator(bytecode_array());
1277   HandlerRangeMatcher try_start_matcher(iterator, bytecode_array());
1278 
1279   bool has_one_shot_bytecode = false;
1280   for (; !iterator.done(); iterator.Advance()) {
1281     has_one_shot_bytecode =
1282         has_one_shot_bytecode ||
1283         interpreter::Bytecodes::IsOneShotBytecode(iterator.current_bytecode());
1284 
1285     int const current_offset = iterator.current_offset();
1286 
1287     // TODO(mvstanton): we might want to ignore the current environment if we
1288     // are at the start of a catch handler.
1289     IncorporateJumpTargetEnvironment(current_offset);
1290 
1291     TRACE_BROKER(broker(),
1292                  "Handling bytecode: " << current_offset << "  "
1293                                        << iterator.current_bytecode());
1294     TRACE_BROKER(broker(), "Current environment: " << *environment());
1295 
1296     if (environment()->IsDead()) {
1297       continue;  // Skip this bytecode since TF won't generate code for it.
1298     }
1299 
1300     auto save_handler_environments = [&](int handler_offset) {
1301       auto it = jump_target_environments_.find(handler_offset);
1302       if (it == jump_target_environments_.end()) {
1303         ContributeToJumpTargetEnvironment(handler_offset);
1304         TRACE_BROKER(broker(),
1305                      "Handler offset for current pos: " << handler_offset);
1306       }
1307     };
1308     try_start_matcher.HandlerOffsetForCurrentPosition(
1309         save_handler_environments);
1310 
1311     if (bytecode_analysis.IsLoopHeader(current_offset)) {
1312       // Graph builder might insert jumps to resume targets in the loop body.
1313       LoopInfo const& loop_info =
1314           bytecode_analysis.GetLoopInfoFor(current_offset);
1315       for (const auto& target : loop_info.resume_jump_targets()) {
1316         ContributeToJumpTargetEnvironment(target.target_offset());
1317       }
1318     }
1319 
1320     switch (iterator.current_bytecode()) {
1321 #define DEFINE_BYTECODE_CASE(name)     \
1322   case interpreter::Bytecode::k##name: \
1323     Visit##name(&iterator);            \
1324     break;
1325       SUPPORTED_BYTECODE_LIST(DEFINE_BYTECODE_CASE)
1326 #undef DEFINE_BYTECODE_CASE
1327     }
1328   }
1329 
1330   if (has_one_shot_bytecode) {
1331     broker()->isolate()->CountUsage(
1332         v8::Isolate::UseCounterFeature::kOptimizedFunctionWithOneShotBytecode);
1333   }
1334 }
1335 
VisitGetIterator(BytecodeArrayIterator * iterator)1336 void SerializerForBackgroundCompilation::VisitGetIterator(
1337     BytecodeArrayIterator* iterator) {
1338   Hints* receiver = &register_hints(iterator->GetRegisterOperand(0));
1339   FeedbackSlot load_slot = iterator->GetSlotOperand(1);
1340   FeedbackSlot call_slot = iterator->GetSlotOperand(2);
1341 
1342   Handle<Name> name = broker()->isolate()->factory()->iterator_symbol();
1343   ProcessNamedPropertyAccess(receiver, NameRef(broker(), name), load_slot,
1344                              AccessMode::kLoad);
1345   if (environment()->IsDead()) return;
1346 
1347   Hints callee;
1348   HintsVector args = PrepareArgumentsHints(receiver);
1349 
1350   ProcessCallOrConstruct(callee, base::nullopt, &args, call_slot,
1351                          kMissingArgumentsAreUndefined);
1352 }
1353 
VisitGetSuperConstructor(BytecodeArrayIterator * iterator)1354 void SerializerForBackgroundCompilation::VisitGetSuperConstructor(
1355     BytecodeArrayIterator* iterator) {
1356   interpreter::Register dst = iterator->GetRegisterOperand(0);
1357   Hints result_hints;
1358   for (auto constant : environment()->accumulator_hints().constants()) {
1359     // For JSNativeContextSpecialization::ReduceJSGetSuperConstructor.
1360     if (!constant->IsJSFunction()) continue;
1361     MapRef map(broker(),
1362                handle(HeapObject::cast(*constant).map(), broker()->isolate()));
1363     map.SerializePrototype();
1364     ObjectRef proto = map.prototype();
1365     if (proto.IsHeapObject() && proto.AsHeapObject().map().is_constructor()) {
1366       result_hints.AddConstant(proto.object(), zone(), broker());
1367     }
1368   }
1369   register_hints(dst) = result_hints;
1370 }
1371 
VisitGetTemplateObject(BytecodeArrayIterator * iterator)1372 void SerializerForBackgroundCompilation::VisitGetTemplateObject(
1373     BytecodeArrayIterator* iterator) {
1374   TemplateObjectDescriptionRef description(
1375       broker(), iterator->GetConstantForIndexOperand(0, broker()->isolate()));
1376   FeedbackSlot slot = iterator->GetSlotOperand(1);
1377   FeedbackSource source(feedback_vector(), slot);
1378   SharedFunctionInfoRef shared(broker(), function().shared());
1379   JSArrayRef template_object = shared.GetTemplateObject(
1380       description, source, SerializationPolicy::kSerializeIfNeeded);
1381   environment()->accumulator_hints() =
1382       Hints::SingleConstant(template_object.object(), zone());
1383 }
1384 
VisitLdaTrue(BytecodeArrayIterator * iterator)1385 void SerializerForBackgroundCompilation::VisitLdaTrue(
1386     BytecodeArrayIterator* iterator) {
1387   environment()->accumulator_hints() = Hints::SingleConstant(
1388       broker()->isolate()->factory()->true_value(), zone());
1389 }
1390 
VisitLdaFalse(BytecodeArrayIterator * iterator)1391 void SerializerForBackgroundCompilation::VisitLdaFalse(
1392     BytecodeArrayIterator* iterator) {
1393   environment()->accumulator_hints() = Hints::SingleConstant(
1394       broker()->isolate()->factory()->false_value(), zone());
1395 }
1396 
VisitLdaTheHole(BytecodeArrayIterator * iterator)1397 void SerializerForBackgroundCompilation::VisitLdaTheHole(
1398     BytecodeArrayIterator* iterator) {
1399   environment()->accumulator_hints() = Hints::SingleConstant(
1400       broker()->isolate()->factory()->the_hole_value(), zone());
1401 }
1402 
VisitLdaUndefined(BytecodeArrayIterator * iterator)1403 void SerializerForBackgroundCompilation::VisitLdaUndefined(
1404     BytecodeArrayIterator* iterator) {
1405   environment()->accumulator_hints() = Hints::SingleConstant(
1406       broker()->isolate()->factory()->undefined_value(), zone());
1407 }
1408 
VisitLdaNull(BytecodeArrayIterator * iterator)1409 void SerializerForBackgroundCompilation::VisitLdaNull(
1410     BytecodeArrayIterator* iterator) {
1411   environment()->accumulator_hints() = Hints::SingleConstant(
1412       broker()->isolate()->factory()->null_value(), zone());
1413 }
1414 
VisitLdaZero(BytecodeArrayIterator * iterator)1415 void SerializerForBackgroundCompilation::VisitLdaZero(
1416     BytecodeArrayIterator* iterator) {
1417   environment()->accumulator_hints() = Hints::SingleConstant(
1418       handle(Smi::FromInt(0), broker()->isolate()), zone());
1419 }
1420 
VisitLdaSmi(BytecodeArrayIterator * iterator)1421 void SerializerForBackgroundCompilation::VisitLdaSmi(
1422     BytecodeArrayIterator* iterator) {
1423   Handle<Smi> smi(Smi::FromInt(iterator->GetImmediateOperand(0)),
1424                   broker()->isolate());
1425   environment()->accumulator_hints() = Hints::SingleConstant(smi, zone());
1426 }
1427 
VisitInvokeIntrinsic(BytecodeArrayIterator * iterator)1428 void SerializerForBackgroundCompilation::VisitInvokeIntrinsic(
1429     BytecodeArrayIterator* iterator) {
1430   Runtime::FunctionId functionId = iterator->GetIntrinsicIdOperand(0);
1431   // For JSNativeContextSpecialization::ReduceJSAsyncFunctionResolve and
1432   // JSNativeContextSpecialization::ReduceJSResolvePromise.
1433   switch (functionId) {
1434     case Runtime::kInlineAsyncFunctionResolve: {
1435       ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
1436                               Builtins::kAsyncFunctionResolve));
1437       interpreter::Register first_reg = iterator->GetRegisterOperand(1);
1438       size_t reg_count = iterator->GetRegisterCountOperand(2);
1439       CHECK_EQ(reg_count, 3);
1440       HintsVector args = PrepareArgumentsHints(first_reg, reg_count);
1441       Hints const& resolution_hints = args[1];  // The resolution object.
1442       ProcessHintsForPromiseResolve(resolution_hints);
1443       return;
1444     }
1445     case Runtime::kInlineAsyncGeneratorReject:
1446     case Runtime::kAsyncGeneratorReject: {
1447       ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
1448                               Builtins::kAsyncGeneratorReject));
1449       break;
1450     }
1451     case Runtime::kInlineAsyncGeneratorResolve:
1452     case Runtime::kAsyncGeneratorResolve: {
1453       ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
1454                               Builtins::kAsyncGeneratorResolve));
1455       break;
1456     }
1457     case Runtime::kInlineAsyncGeneratorYield:
1458     case Runtime::kAsyncGeneratorYield: {
1459       ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
1460                               Builtins::kAsyncGeneratorYield));
1461       break;
1462     }
1463     case Runtime::kInlineAsyncGeneratorAwaitUncaught:
1464     case Runtime::kAsyncGeneratorAwaitUncaught: {
1465       ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
1466                               Builtins::kAsyncGeneratorAwaitUncaught));
1467       break;
1468     }
1469     case Runtime::kInlineAsyncGeneratorAwaitCaught:
1470     case Runtime::kAsyncGeneratorAwaitCaught: {
1471       ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
1472                               Builtins::kAsyncGeneratorAwaitCaught));
1473       break;
1474     }
1475     case Runtime::kInlineAsyncFunctionAwaitUncaught:
1476     case Runtime::kAsyncFunctionAwaitUncaught: {
1477       ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
1478                               Builtins::kAsyncFunctionAwaitUncaught));
1479       break;
1480     }
1481     case Runtime::kInlineAsyncFunctionAwaitCaught:
1482     case Runtime::kAsyncFunctionAwaitCaught: {
1483       ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
1484                               Builtins::kAsyncFunctionAwaitCaught));
1485       break;
1486     }
1487     case Runtime::kInlineAsyncFunctionReject:
1488     case Runtime::kAsyncFunctionReject: {
1489       ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
1490                               Builtins::kAsyncFunctionReject));
1491       break;
1492     }
1493     case Runtime::kAsyncFunctionResolve: {
1494       ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
1495                               Builtins::kAsyncFunctionResolve));
1496       break;
1497     }
1498     case Runtime::kInlineCopyDataProperties:
1499     case Runtime::kCopyDataProperties: {
1500       ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
1501                               Builtins::kCopyDataProperties));
1502       break;
1503     }
1504     case Runtime::kInlineGetImportMetaObject: {
1505       Hints const& context_hints = environment()->current_context_hints();
1506       for (auto x : context_hints.constants()) {
1507         ContextRef(broker(), x)
1508             .GetModule(SerializationPolicy::kSerializeIfNeeded)
1509             .Serialize();
1510       }
1511       for (auto x : context_hints.virtual_contexts()) {
1512         ContextRef(broker(), x.context)
1513             .GetModule(SerializationPolicy::kSerializeIfNeeded)
1514             .Serialize();
1515       }
1516       break;
1517     }
1518     default: {
1519       break;
1520     }
1521   }
1522   environment()->accumulator_hints() = Hints();
1523 }
1524 
VisitLdaConstant(BytecodeArrayIterator * iterator)1525 void SerializerForBackgroundCompilation::VisitLdaConstant(
1526     BytecodeArrayIterator* iterator) {
1527   ObjectRef object(
1528       broker(), iterator->GetConstantForIndexOperand(0, broker()->isolate()));
1529   environment()->accumulator_hints() =
1530       Hints::SingleConstant(object.object(), zone());
1531 }
1532 
VisitPushContext(BytecodeArrayIterator * iterator)1533 void SerializerForBackgroundCompilation::VisitPushContext(
1534     BytecodeArrayIterator* iterator) {
1535   register_hints(iterator->GetRegisterOperand(0))
1536       .Reset(&environment()->current_context_hints(), zone());
1537   environment()->current_context_hints().Reset(
1538       &environment()->accumulator_hints(), zone());
1539 }
1540 
VisitPopContext(BytecodeArrayIterator * iterator)1541 void SerializerForBackgroundCompilation::VisitPopContext(
1542     BytecodeArrayIterator* iterator) {
1543   environment()->current_context_hints().Reset(
1544       &register_hints(iterator->GetRegisterOperand(0)), zone());
1545 }
1546 
ProcessImmutableLoad(ContextRef const & context_ref,int slot,ContextProcessingMode mode,Hints * result_hints)1547 void SerializerForBackgroundCompilation::ProcessImmutableLoad(
1548     ContextRef const& context_ref, int slot, ContextProcessingMode mode,
1549     Hints* result_hints) {
1550   DCHECK_EQ(mode, kSerializeSlot);
1551   base::Optional<ObjectRef> slot_value =
1552       context_ref.get(slot, SerializationPolicy::kSerializeIfNeeded);
1553 
1554   // If requested, record the object as a hint for the result value.
1555   if (result_hints != nullptr && slot_value.has_value()) {
1556     result_hints->AddConstant(slot_value.value().object(), zone(), broker());
1557   }
1558 }
1559 
ProcessContextAccess(Hints const & context_hints,int slot,int depth,ContextProcessingMode mode,Hints * result_hints)1560 void SerializerForBackgroundCompilation::ProcessContextAccess(
1561     Hints const& context_hints, int slot, int depth, ContextProcessingMode mode,
1562     Hints* result_hints) {
1563   // This function is for JSContextSpecialization::ReduceJSLoadContext and
1564   // ReduceJSStoreContext. Those reductions attempt to eliminate as many
1565   // loads as possible by making use of constant Context objects. In the
1566   // case of an immutable load, ReduceJSLoadContext even attempts to load
1567   // the value at {slot}, replacing the load with a constant.
1568   for (auto x : context_hints.constants()) {
1569     if (x->IsContext()) {
1570       // Walk this context to the given depth and serialize the slot found.
1571       ContextRef context_ref(broker(), x);
1572       size_t remaining_depth = depth;
1573       context_ref = context_ref.previous(
1574           &remaining_depth, SerializationPolicy::kSerializeIfNeeded);
1575       if (remaining_depth == 0 && mode != kIgnoreSlot) {
1576         ProcessImmutableLoad(context_ref, slot, mode, result_hints);
1577       }
1578     }
1579   }
1580   for (auto x : context_hints.virtual_contexts()) {
1581     if (x.distance <= static_cast<unsigned int>(depth)) {
1582       ContextRef context_ref(broker(), x.context);
1583       size_t remaining_depth = depth - x.distance;
1584       context_ref = context_ref.previous(
1585           &remaining_depth, SerializationPolicy::kSerializeIfNeeded);
1586       if (remaining_depth == 0 && mode != kIgnoreSlot) {
1587         ProcessImmutableLoad(context_ref, slot, mode, result_hints);
1588       }
1589     }
1590   }
1591 }
1592 
VisitLdaContextSlot(BytecodeArrayIterator * iterator)1593 void SerializerForBackgroundCompilation::VisitLdaContextSlot(
1594     BytecodeArrayIterator* iterator) {
1595   Hints const& context_hints = register_hints(iterator->GetRegisterOperand(0));
1596   const int slot = iterator->GetIndexOperand(1);
1597   const int depth = iterator->GetUnsignedImmediateOperand(2);
1598   Hints new_accumulator_hints;
1599   ProcessContextAccess(context_hints, slot, depth, kIgnoreSlot,
1600                        &new_accumulator_hints);
1601   environment()->accumulator_hints() = new_accumulator_hints;
1602 }
1603 
VisitLdaCurrentContextSlot(BytecodeArrayIterator * iterator)1604 void SerializerForBackgroundCompilation::VisitLdaCurrentContextSlot(
1605     BytecodeArrayIterator* iterator) {
1606   const int slot = iterator->GetIndexOperand(0);
1607   const int depth = 0;
1608   Hints const& context_hints = environment()->current_context_hints();
1609   Hints new_accumulator_hints;
1610   ProcessContextAccess(context_hints, slot, depth, kIgnoreSlot,
1611                        &new_accumulator_hints);
1612   environment()->accumulator_hints() = new_accumulator_hints;
1613 }
1614 
VisitLdaImmutableContextSlot(BytecodeArrayIterator * iterator)1615 void SerializerForBackgroundCompilation::VisitLdaImmutableContextSlot(
1616     BytecodeArrayIterator* iterator) {
1617   const int slot = iterator->GetIndexOperand(1);
1618   const int depth = iterator->GetUnsignedImmediateOperand(2);
1619   Hints const& context_hints = register_hints(iterator->GetRegisterOperand(0));
1620   Hints new_accumulator_hints;
1621   ProcessContextAccess(context_hints, slot, depth, kSerializeSlot,
1622                        &new_accumulator_hints);
1623   environment()->accumulator_hints() = new_accumulator_hints;
1624 }
1625 
VisitLdaImmutableCurrentContextSlot(BytecodeArrayIterator * iterator)1626 void SerializerForBackgroundCompilation::VisitLdaImmutableCurrentContextSlot(
1627     BytecodeArrayIterator* iterator) {
1628   const int slot = iterator->GetIndexOperand(0);
1629   const int depth = 0;
1630   Hints const& context_hints = environment()->current_context_hints();
1631   Hints new_accumulator_hints;
1632   ProcessContextAccess(context_hints, slot, depth, kSerializeSlot,
1633                        &new_accumulator_hints);
1634   environment()->accumulator_hints() = new_accumulator_hints;
1635 }
1636 
ProcessModuleVariableAccess(BytecodeArrayIterator * iterator)1637 void SerializerForBackgroundCompilation::ProcessModuleVariableAccess(
1638     BytecodeArrayIterator* iterator) {
1639   const int slot = Context::EXTENSION_INDEX;
1640   const int depth = iterator->GetUnsignedImmediateOperand(1);
1641   Hints const& context_hints = environment()->current_context_hints();
1642 
1643   Hints result_hints;
1644   ProcessContextAccess(context_hints, slot, depth, kSerializeSlot,
1645                        &result_hints);
1646   for (Handle<Object> constant : result_hints.constants()) {
1647     ObjectRef object(broker(), constant);
1648     // For JSTypedLowering::BuildGetModuleCell.
1649     if (object.IsSourceTextModule()) object.AsSourceTextModule().Serialize();
1650   }
1651 }
1652 
VisitLdaModuleVariable(BytecodeArrayIterator * iterator)1653 void SerializerForBackgroundCompilation::VisitLdaModuleVariable(
1654     BytecodeArrayIterator* iterator) {
1655   ProcessModuleVariableAccess(iterator);
1656 }
1657 
VisitStaModuleVariable(BytecodeArrayIterator * iterator)1658 void SerializerForBackgroundCompilation::VisitStaModuleVariable(
1659     BytecodeArrayIterator* iterator) {
1660   ProcessModuleVariableAccess(iterator);
1661 }
1662 
VisitStaLookupSlot(BytecodeArrayIterator * iterator)1663 void SerializerForBackgroundCompilation::VisitStaLookupSlot(
1664     BytecodeArrayIterator* iterator) {
1665   ObjectRef(broker(),
1666             iterator->GetConstantForIndexOperand(0, broker()->isolate()));
1667   environment()->accumulator_hints() = Hints();
1668 }
1669 
VisitStaContextSlot(BytecodeArrayIterator * iterator)1670 void SerializerForBackgroundCompilation::VisitStaContextSlot(
1671     BytecodeArrayIterator* iterator) {
1672   const int slot = iterator->GetIndexOperand(1);
1673   const int depth = iterator->GetUnsignedImmediateOperand(2);
1674   Hints const& hints = register_hints(iterator->GetRegisterOperand(0));
1675   ProcessContextAccess(hints, slot, depth, kIgnoreSlot);
1676 }
1677 
VisitStaCurrentContextSlot(BytecodeArrayIterator * iterator)1678 void SerializerForBackgroundCompilation::VisitStaCurrentContextSlot(
1679     BytecodeArrayIterator* iterator) {
1680   const int slot = iterator->GetIndexOperand(0);
1681   const int depth = 0;
1682   Hints const& context_hints = environment()->current_context_hints();
1683   ProcessContextAccess(context_hints, slot, depth, kIgnoreSlot);
1684 }
1685 
VisitLdar(BytecodeArrayIterator * iterator)1686 void SerializerForBackgroundCompilation::VisitLdar(
1687     BytecodeArrayIterator* iterator) {
1688   environment()->accumulator_hints().Reset(
1689       &register_hints(iterator->GetRegisterOperand(0)), zone());
1690 }
1691 
VisitStar(BytecodeArrayIterator * iterator)1692 void SerializerForBackgroundCompilation::VisitStar(
1693     BytecodeArrayIterator* iterator) {
1694   interpreter::Register reg = iterator->GetRegisterOperand(0);
1695   register_hints(reg).Reset(&environment()->accumulator_hints(), zone());
1696 }
1697 
VisitMov(BytecodeArrayIterator * iterator)1698 void SerializerForBackgroundCompilation::VisitMov(
1699     BytecodeArrayIterator* iterator) {
1700   interpreter::Register src = iterator->GetRegisterOperand(0);
1701   interpreter::Register dst = iterator->GetRegisterOperand(1);
1702   register_hints(dst).Reset(&register_hints(src), zone());
1703 }
1704 
VisitCreateRegExpLiteral(BytecodeArrayIterator * iterator)1705 void SerializerForBackgroundCompilation::VisitCreateRegExpLiteral(
1706     BytecodeArrayIterator* iterator) {
1707   Handle<String> constant_pattern = Handle<String>::cast(
1708       iterator->GetConstantForIndexOperand(0, broker()->isolate()));
1709   StringRef description(broker(), constant_pattern);
1710   FeedbackSlot slot = iterator->GetSlotOperand(1);
1711   FeedbackSource source(feedback_vector(), slot);
1712   broker()->ProcessFeedbackForRegExpLiteral(source);
1713   environment()->accumulator_hints() = Hints();
1714 }
1715 
VisitCreateArrayLiteral(BytecodeArrayIterator * iterator)1716 void SerializerForBackgroundCompilation::VisitCreateArrayLiteral(
1717     BytecodeArrayIterator* iterator) {
1718   Handle<ArrayBoilerplateDescription> array_boilerplate_description =
1719       Handle<ArrayBoilerplateDescription>::cast(
1720           iterator->GetConstantForIndexOperand(0, broker()->isolate()));
1721   ArrayBoilerplateDescriptionRef description(broker(),
1722                                              array_boilerplate_description);
1723   FeedbackSlot slot = iterator->GetSlotOperand(1);
1724   FeedbackSource source(feedback_vector(), slot);
1725   broker()->ProcessFeedbackForArrayOrObjectLiteral(source);
1726   environment()->accumulator_hints() = Hints();
1727 }
1728 
VisitCreateEmptyArrayLiteral(BytecodeArrayIterator * iterator)1729 void SerializerForBackgroundCompilation::VisitCreateEmptyArrayLiteral(
1730     BytecodeArrayIterator* iterator) {
1731   FeedbackSlot slot = iterator->GetSlotOperand(0);
1732   FeedbackSource source(feedback_vector(), slot);
1733   broker()->ProcessFeedbackForArrayOrObjectLiteral(source);
1734   environment()->accumulator_hints() = Hints();
1735 }
1736 
VisitCreateObjectLiteral(BytecodeArrayIterator * iterator)1737 void SerializerForBackgroundCompilation::VisitCreateObjectLiteral(
1738     BytecodeArrayIterator* iterator) {
1739   Handle<ObjectBoilerplateDescription> constant_properties =
1740       Handle<ObjectBoilerplateDescription>::cast(
1741           iterator->GetConstantForIndexOperand(0, broker()->isolate()));
1742   ObjectBoilerplateDescriptionRef description(broker(), constant_properties);
1743   FeedbackSlot slot = iterator->GetSlotOperand(1);
1744   FeedbackSource source(feedback_vector(), slot);
1745   broker()->ProcessFeedbackForArrayOrObjectLiteral(source);
1746   environment()->accumulator_hints() = Hints();
1747 }
1748 
VisitCreateFunctionContext(BytecodeArrayIterator * iterator)1749 void SerializerForBackgroundCompilation::VisitCreateFunctionContext(
1750     BytecodeArrayIterator* iterator) {
1751   ProcessCreateContext(iterator, 0);
1752 }
1753 
VisitCreateBlockContext(BytecodeArrayIterator * iterator)1754 void SerializerForBackgroundCompilation::VisitCreateBlockContext(
1755     BytecodeArrayIterator* iterator) {
1756   ProcessCreateContext(iterator, 0);
1757 }
1758 
VisitCreateEvalContext(BytecodeArrayIterator * iterator)1759 void SerializerForBackgroundCompilation::VisitCreateEvalContext(
1760     BytecodeArrayIterator* iterator) {
1761   ProcessCreateContext(iterator, 0);
1762 }
1763 
VisitCreateWithContext(BytecodeArrayIterator * iterator)1764 void SerializerForBackgroundCompilation::VisitCreateWithContext(
1765     BytecodeArrayIterator* iterator) {
1766   ProcessCreateContext(iterator, 1);
1767 }
1768 
VisitCreateCatchContext(BytecodeArrayIterator * iterator)1769 void SerializerForBackgroundCompilation::VisitCreateCatchContext(
1770     BytecodeArrayIterator* iterator) {
1771   ProcessCreateContext(iterator, 1);
1772 }
1773 
VisitForInNext(BytecodeArrayIterator * iterator)1774 void SerializerForBackgroundCompilation::VisitForInNext(
1775     BytecodeArrayIterator* iterator) {
1776   FeedbackSlot slot = iterator->GetSlotOperand(3);
1777   ProcessForIn(slot);
1778 }
1779 
VisitForInPrepare(BytecodeArrayIterator * iterator)1780 void SerializerForBackgroundCompilation::VisitForInPrepare(
1781     BytecodeArrayIterator* iterator) {
1782   FeedbackSlot slot = iterator->GetSlotOperand(1);
1783   ProcessForIn(slot);
1784 }
1785 
ProcessCreateContext(interpreter::BytecodeArrayIterator * iterator,int scopeinfo_operand_index)1786 void SerializerForBackgroundCompilation::ProcessCreateContext(
1787     interpreter::BytecodeArrayIterator* iterator, int scopeinfo_operand_index) {
1788   Handle<ScopeInfo> scope_info =
1789       Handle<ScopeInfo>::cast(iterator->GetConstantForIndexOperand(
1790           scopeinfo_operand_index, broker()->isolate()));
1791   ScopeInfoRef scope_info_ref(broker(), scope_info);
1792   scope_info_ref.SerializeScopeInfoChain();
1793 
1794   Hints const& current_context_hints = environment()->current_context_hints();
1795   Hints result_hints;
1796 
1797   // For each constant context, we must create a virtual context from
1798   // it of distance one.
1799   for (auto x : current_context_hints.constants()) {
1800     if (x->IsContext()) {
1801       Handle<Context> as_context(Handle<Context>::cast(x));
1802       result_hints.AddVirtualContext(VirtualContext(1, as_context), zone(),
1803                                      broker());
1804     }
1805   }
1806 
1807   // For each virtual context, we must create a virtual context from
1808   // it of distance {existing distance} + 1.
1809   for (auto x : current_context_hints.virtual_contexts()) {
1810     result_hints.AddVirtualContext(VirtualContext(x.distance + 1, x.context),
1811                                    zone(), broker());
1812   }
1813 
1814   environment()->accumulator_hints() = result_hints;
1815 }
1816 
VisitCreateClosure(BytecodeArrayIterator * iterator)1817 void SerializerForBackgroundCompilation::VisitCreateClosure(
1818     BytecodeArrayIterator* iterator) {
1819   Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(
1820       iterator->GetConstantForIndexOperand(0, broker()->isolate()));
1821   Handle<FeedbackCell> feedback_cell =
1822       feedback_vector()->GetClosureFeedbackCell(iterator->GetIndexOperand(1));
1823   FeedbackCellRef feedback_cell_ref(broker(), feedback_cell);
1824   Handle<Object> cell_value(feedback_cell->value(), broker()->isolate());
1825   ObjectRef cell_value_ref(broker(), cell_value);
1826 
1827   Hints result_hints;
1828   if (cell_value->IsFeedbackVector()) {
1829     VirtualClosure virtual_closure(shared,
1830                                    Handle<FeedbackVector>::cast(cell_value),
1831                                    environment()->current_context_hints());
1832     result_hints.AddVirtualClosure(virtual_closure, zone(), broker());
1833   }
1834   environment()->accumulator_hints() = result_hints;
1835 }
1836 
VisitCallUndefinedReceiver(BytecodeArrayIterator * iterator)1837 void SerializerForBackgroundCompilation::VisitCallUndefinedReceiver(
1838     BytecodeArrayIterator* iterator) {
1839   Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
1840   interpreter::Register first_reg = iterator->GetRegisterOperand(1);
1841   int reg_count = static_cast<int>(iterator->GetRegisterCountOperand(2));
1842   FeedbackSlot slot = iterator->GetSlotOperand(3);
1843   ProcessCallVarArgs(ConvertReceiverMode::kNullOrUndefined, callee, first_reg,
1844                      reg_count, slot);
1845 }
1846 
VisitCallUndefinedReceiver0(BytecodeArrayIterator * iterator)1847 void SerializerForBackgroundCompilation::VisitCallUndefinedReceiver0(
1848     BytecodeArrayIterator* iterator) {
1849   Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
1850   FeedbackSlot slot = iterator->GetSlotOperand(1);
1851 
1852   Hints const receiver = Hints::SingleConstant(
1853       broker()->isolate()->factory()->undefined_value(), zone());
1854   HintsVector parameters({receiver}, zone());
1855 
1856   ProcessCallOrConstruct(callee, base::nullopt, &parameters, slot,
1857                          kMissingArgumentsAreUndefined);
1858 }
1859 
1860 namespace {
PrepareArgumentsHintsInternal(Zone * zone,HintsVector * args)1861 void PrepareArgumentsHintsInternal(Zone* zone, HintsVector* args) {}
1862 
1863 template <typename... MoreHints>
PrepareArgumentsHintsInternal(Zone * zone,HintsVector * args,Hints * hints,MoreHints...more)1864 void PrepareArgumentsHintsInternal(Zone* zone, HintsVector* args, Hints* hints,
1865                                    MoreHints... more) {
1866   hints->EnsureShareable(zone);
1867   args->push_back(*hints);
1868   PrepareArgumentsHintsInternal(zone, args, more...);
1869 }
1870 }  // namespace
1871 
1872 template <typename... MoreHints>
PrepareArgumentsHints(Hints * hints,MoreHints...more)1873 HintsVector SerializerForBackgroundCompilation::PrepareArgumentsHints(
1874     Hints* hints, MoreHints... more) {
1875   HintsVector args(zone());
1876   PrepareArgumentsHintsInternal(zone(), &args, hints, more...);
1877   return args;
1878 }
1879 
PrepareArgumentsHints(interpreter::Register first,size_t count)1880 HintsVector SerializerForBackgroundCompilation::PrepareArgumentsHints(
1881     interpreter::Register first, size_t count) {
1882   HintsVector result(zone());
1883   const int reg_base = first.index();
1884   for (int i = 0; i < static_cast<int>(count); ++i) {
1885     Hints& hints = register_hints(interpreter::Register(reg_base + i));
1886     hints.EnsureShareable(zone());
1887     result.push_back(hints);
1888   }
1889   return result;
1890 }
1891 
VisitCallUndefinedReceiver1(BytecodeArrayIterator * iterator)1892 void SerializerForBackgroundCompilation::VisitCallUndefinedReceiver1(
1893     BytecodeArrayIterator* iterator) {
1894   Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
1895   Hints* arg0 = &register_hints(iterator->GetRegisterOperand(1));
1896   FeedbackSlot slot = iterator->GetSlotOperand(2);
1897 
1898   Hints receiver = Hints::SingleConstant(
1899       broker()->isolate()->factory()->undefined_value(), zone());
1900   HintsVector args = PrepareArgumentsHints(&receiver, arg0);
1901 
1902   ProcessCallOrConstruct(callee, base::nullopt, &args, slot,
1903                          kMissingArgumentsAreUndefined);
1904 }
1905 
VisitCallUndefinedReceiver2(BytecodeArrayIterator * iterator)1906 void SerializerForBackgroundCompilation::VisitCallUndefinedReceiver2(
1907     BytecodeArrayIterator* iterator) {
1908   Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
1909   Hints* arg0 = &register_hints(iterator->GetRegisterOperand(1));
1910   Hints* arg1 = &register_hints(iterator->GetRegisterOperand(2));
1911   FeedbackSlot slot = iterator->GetSlotOperand(3);
1912 
1913   Hints receiver = Hints::SingleConstant(
1914       broker()->isolate()->factory()->undefined_value(), zone());
1915   HintsVector args = PrepareArgumentsHints(&receiver, arg0, arg1);
1916 
1917   ProcessCallOrConstruct(callee, base::nullopt, &args, slot,
1918                          kMissingArgumentsAreUndefined);
1919 }
1920 
VisitCallAnyReceiver(BytecodeArrayIterator * iterator)1921 void SerializerForBackgroundCompilation::VisitCallAnyReceiver(
1922     BytecodeArrayIterator* iterator) {
1923   Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
1924   interpreter::Register first_reg = iterator->GetRegisterOperand(1);
1925   int reg_count = static_cast<int>(iterator->GetRegisterCountOperand(2));
1926   FeedbackSlot slot = iterator->GetSlotOperand(3);
1927   ProcessCallVarArgs(ConvertReceiverMode::kAny, callee, first_reg, reg_count,
1928                      slot);
1929 }
1930 
VisitCallNoFeedback(BytecodeArrayIterator * iterator)1931 void SerializerForBackgroundCompilation::VisitCallNoFeedback(
1932     BytecodeArrayIterator* iterator) {
1933   Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
1934   interpreter::Register first_reg = iterator->GetRegisterOperand(1);
1935   int reg_count = static_cast<int>(iterator->GetRegisterCountOperand(2));
1936   ProcessCallVarArgs(ConvertReceiverMode::kAny, callee, first_reg, reg_count,
1937                      FeedbackSlot::Invalid());
1938 }
1939 
VisitCallProperty(BytecodeArrayIterator * iterator)1940 void SerializerForBackgroundCompilation::VisitCallProperty(
1941     BytecodeArrayIterator* iterator) {
1942   Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
1943   interpreter::Register first_reg = iterator->GetRegisterOperand(1);
1944   int reg_count = static_cast<int>(iterator->GetRegisterCountOperand(2));
1945   FeedbackSlot slot = iterator->GetSlotOperand(3);
1946   ProcessCallVarArgs(ConvertReceiverMode::kNotNullOrUndefined, callee,
1947                      first_reg, reg_count, slot);
1948 }
1949 
VisitCallProperty0(BytecodeArrayIterator * iterator)1950 void SerializerForBackgroundCompilation::VisitCallProperty0(
1951     BytecodeArrayIterator* iterator) {
1952   Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
1953   Hints* receiver = &register_hints(iterator->GetRegisterOperand(1));
1954   FeedbackSlot slot = iterator->GetSlotOperand(2);
1955 
1956   HintsVector args = PrepareArgumentsHints(receiver);
1957 
1958   ProcessCallOrConstruct(callee, base::nullopt, &args, slot,
1959                          kMissingArgumentsAreUndefined);
1960 }
1961 
VisitCallProperty1(BytecodeArrayIterator * iterator)1962 void SerializerForBackgroundCompilation::VisitCallProperty1(
1963     BytecodeArrayIterator* iterator) {
1964   Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
1965   Hints* receiver = &register_hints(iterator->GetRegisterOperand(1));
1966   Hints* arg0 = &register_hints(iterator->GetRegisterOperand(2));
1967   FeedbackSlot slot = iterator->GetSlotOperand(3);
1968 
1969   HintsVector args = PrepareArgumentsHints(receiver, arg0);
1970 
1971   ProcessCallOrConstruct(callee, base::nullopt, &args, slot,
1972                          kMissingArgumentsAreUndefined);
1973 }
1974 
VisitCallProperty2(BytecodeArrayIterator * iterator)1975 void SerializerForBackgroundCompilation::VisitCallProperty2(
1976     BytecodeArrayIterator* iterator) {
1977   Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
1978   Hints* receiver = &register_hints(iterator->GetRegisterOperand(1));
1979   Hints* arg0 = &register_hints(iterator->GetRegisterOperand(2));
1980   Hints* arg1 = &register_hints(iterator->GetRegisterOperand(3));
1981   FeedbackSlot slot = iterator->GetSlotOperand(4);
1982 
1983   HintsVector args = PrepareArgumentsHints(receiver, arg0, arg1);
1984 
1985   ProcessCallOrConstruct(callee, base::nullopt, &args, slot,
1986                          kMissingArgumentsAreUndefined);
1987 }
1988 
VisitCallWithSpread(BytecodeArrayIterator * iterator)1989 void SerializerForBackgroundCompilation::VisitCallWithSpread(
1990     BytecodeArrayIterator* iterator) {
1991   Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
1992   interpreter::Register first_reg = iterator->GetRegisterOperand(1);
1993   int reg_count = static_cast<int>(iterator->GetRegisterCountOperand(2));
1994   FeedbackSlot slot = iterator->GetSlotOperand(3);
1995   ProcessCallVarArgs(ConvertReceiverMode::kAny, callee, first_reg, reg_count,
1996                      slot, kMissingArgumentsAreUnknown);
1997 }
1998 
VisitCallJSRuntime(BytecodeArrayIterator * iterator)1999 void SerializerForBackgroundCompilation::VisitCallJSRuntime(
2000     BytecodeArrayIterator* iterator) {
2001   const int runtime_index = iterator->GetNativeContextIndexOperand(0);
2002   ObjectRef constant =
2003       broker()
2004           ->target_native_context()
2005           .get(runtime_index, SerializationPolicy::kSerializeIfNeeded)
2006           .value();
2007   Hints const callee = Hints::SingleConstant(constant.object(), zone());
2008   interpreter::Register first_reg = iterator->GetRegisterOperand(1);
2009   int reg_count = static_cast<int>(iterator->GetRegisterCountOperand(2));
2010   ProcessCallVarArgs(ConvertReceiverMode::kNullOrUndefined, callee, first_reg,
2011                      reg_count, FeedbackSlot::Invalid());
2012 }
2013 
RunChildSerializer(CompilationSubject function,base::Optional<Hints> new_target,const HintsVector & arguments,MissingArgumentsPolicy padding)2014 Hints SerializerForBackgroundCompilation::RunChildSerializer(
2015     CompilationSubject function, base::Optional<Hints> new_target,
2016     const HintsVector& arguments, MissingArgumentsPolicy padding) {
2017   SerializerForBackgroundCompilation child_serializer(
2018       zone_scope_.zone_stats(), broker(), dependencies(), function, new_target,
2019       arguments, padding, flags(), nesting_level_ + 1);
2020   Hints result = child_serializer.Run();
2021   // The Hints returned by the call to Run are allocated in the zone
2022   // created by the child serializer. Adding those hints to a hints
2023   // object created in our zone will preserve the information.
2024   return result.CopyToParentZone(zone(), broker());
2025 }
2026 
ProcessCalleeForCallOrConstruct(Callee const & callee,base::Optional<Hints> new_target,const HintsVector & arguments,SpeculationMode speculation_mode,MissingArgumentsPolicy padding,Hints * result_hints)2027 void SerializerForBackgroundCompilation::ProcessCalleeForCallOrConstruct(
2028     Callee const& callee, base::Optional<Hints> new_target,
2029     const HintsVector& arguments, SpeculationMode speculation_mode,
2030     MissingArgumentsPolicy padding, Hints* result_hints) {
2031   Handle<SharedFunctionInfo> shared = callee.shared(broker()->isolate());
2032   if (shared->IsApiFunction()) {
2033     ProcessApiCall(shared, arguments);
2034     DCHECK_NE(shared->GetInlineability(), SharedFunctionInfo::kIsInlineable);
2035   } else if (shared->HasBuiltinId()) {
2036     ProcessBuiltinCall(shared, new_target, arguments, speculation_mode, padding,
2037                        result_hints);
2038     DCHECK_NE(shared->GetInlineability(), SharedFunctionInfo::kIsInlineable);
2039   } else if ((flags() &
2040               SerializerForBackgroundCompilationFlag::kEnableTurboInlining) &&
2041              shared->GetInlineability() == SharedFunctionInfo::kIsInlineable &&
2042              callee.HasFeedbackVector()) {
2043     CompilationSubject subject =
2044         callee.ToCompilationSubject(broker()->isolate(), zone());
2045     result_hints->Add(
2046         RunChildSerializer(subject, new_target, arguments, padding), zone(),
2047         broker());
2048   }
2049 }
2050 
2051 namespace {
2052 // Returns the innermost bound target and inserts all bound arguments and
2053 // {original_arguments} into {expanded_arguments} in the appropriate order.
UnrollBoundFunction(JSBoundFunctionRef const & bound_function,JSHeapBroker * broker,const HintsVector & original_arguments,HintsVector * expanded_arguments,Zone * zone)2054 JSReceiverRef UnrollBoundFunction(JSBoundFunctionRef const& bound_function,
2055                                   JSHeapBroker* broker,
2056                                   const HintsVector& original_arguments,
2057                                   HintsVector* expanded_arguments, Zone* zone) {
2058   DCHECK(expanded_arguments->empty());
2059 
2060   JSReceiverRef target = bound_function.AsJSReceiver();
2061   HintsVector reversed_bound_arguments(zone);
2062   for (; target.IsJSBoundFunction();
2063        target = target.AsJSBoundFunction().bound_target_function()) {
2064     for (int i = target.AsJSBoundFunction().bound_arguments().length() - 1;
2065          i >= 0; --i) {
2066       Hints const arg = Hints::SingleConstant(
2067           target.AsJSBoundFunction().bound_arguments().get(i).object(), zone);
2068       reversed_bound_arguments.push_back(arg);
2069     }
2070     Hints const arg = Hints::SingleConstant(
2071         target.AsJSBoundFunction().bound_this().object(), zone);
2072     reversed_bound_arguments.push_back(arg);
2073   }
2074 
2075   expanded_arguments->insert(expanded_arguments->end(),
2076                              reversed_bound_arguments.rbegin(),
2077                              reversed_bound_arguments.rend());
2078   expanded_arguments->insert(expanded_arguments->end(),
2079                              original_arguments.begin(),
2080                              original_arguments.end());
2081 
2082   return target;
2083 }
2084 }  // namespace
2085 
ProcessCalleeForCallOrConstruct(Handle<Object> callee,base::Optional<Hints> new_target,const HintsVector & arguments,SpeculationMode speculation_mode,MissingArgumentsPolicy padding,Hints * result_hints)2086 void SerializerForBackgroundCompilation::ProcessCalleeForCallOrConstruct(
2087     Handle<Object> callee, base::Optional<Hints> new_target,
2088     const HintsVector& arguments, SpeculationMode speculation_mode,
2089     MissingArgumentsPolicy padding, Hints* result_hints) {
2090   const HintsVector* actual_arguments = &arguments;
2091   HintsVector expanded_arguments(zone());
2092   if (callee->IsJSBoundFunction()) {
2093     JSBoundFunctionRef bound_function(broker(),
2094                                       Handle<JSBoundFunction>::cast(callee));
2095     if (!bound_function.Serialize()) return;
2096     callee = UnrollBoundFunction(bound_function, broker(), arguments,
2097                                  &expanded_arguments, zone())
2098                  .object();
2099     actual_arguments = &expanded_arguments;
2100   }
2101   if (!callee->IsJSFunction()) return;
2102 
2103   JSFunctionRef function(broker(), Handle<JSFunction>::cast(callee));
2104   function.Serialize();
2105   Callee new_callee(function.object());
2106   ProcessCalleeForCallOrConstruct(new_callee, new_target, *actual_arguments,
2107                                   speculation_mode, padding, result_hints);
2108 }
2109 
ProcessCallOrConstruct(Hints callee,base::Optional<Hints> new_target,HintsVector * arguments,FeedbackSlot slot,MissingArgumentsPolicy padding)2110 void SerializerForBackgroundCompilation::ProcessCallOrConstruct(
2111     Hints callee, base::Optional<Hints> new_target, HintsVector* arguments,
2112     FeedbackSlot slot, MissingArgumentsPolicy padding) {
2113   SpeculationMode speculation_mode = SpeculationMode::kDisallowSpeculation;
2114 
2115   if (!slot.IsInvalid()) {
2116     FeedbackSource source(feedback_vector(), slot);
2117     ProcessedFeedback const& feedback =
2118         broker()->ProcessFeedbackForCall(source);
2119     if (BailoutOnUninitialized(feedback)) return;
2120 
2121     if (!feedback.IsInsufficient()) {
2122       // Incorporate feedback into hints copy to simplify processing.
2123       // TODO(neis): Modify the original hints instead?
2124       speculation_mode = feedback.AsCall().speculation_mode();
2125       // Incorporate target feedback into hints copy to simplify processing.
2126       base::Optional<HeapObjectRef> target = feedback.AsCall().target();
2127       if (target.has_value() &&
2128           (target->map().is_callable() || target->IsFeedbackCell())) {
2129         callee = callee.Copy(zone());
2130         // TODO(mvstanton): if the map isn't callable then we have an allocation
2131         // site, and it may make sense to add the Array JSFunction constant.
2132         if (new_target.has_value()) {
2133           // Construct; feedback is new_target, which often is also the callee.
2134           new_target = new_target->Copy(zone());
2135           new_target->AddConstant(target->object(), zone(), broker());
2136           callee.AddConstant(target->object(), zone(), broker());
2137         } else {
2138           // Call; target is feedback cell or callee.
2139           if (target->IsFeedbackCell() &&
2140               target->AsFeedbackCell().value().IsFeedbackVector()) {
2141             FeedbackVectorRef vector =
2142                 target->AsFeedbackCell().value().AsFeedbackVector();
2143             vector.Serialize();
2144             VirtualClosure virtual_closure(
2145                 vector.shared_function_info().object(), vector.object(),
2146                 Hints());
2147             callee.AddVirtualClosure(virtual_closure, zone(), broker());
2148           } else {
2149             callee.AddConstant(target->object(), zone(), broker());
2150           }
2151         }
2152       }
2153     }
2154   }
2155 
2156   Hints result_hints_from_new_target;
2157   if (new_target.has_value()) {
2158     ProcessNewTargetForConstruct(*new_target, &result_hints_from_new_target);
2159     // These hints are a good guess at the resulting object, so they are useful
2160     // for both the accumulator and the constructor call's receiver. The latter
2161     // is still missing completely in {arguments} so add it now.
2162     arguments->insert(arguments->begin(), result_hints_from_new_target);
2163   }
2164 
2165   // For JSNativeContextSpecialization::InferRootMap
2166   Hints new_accumulator_hints = result_hints_from_new_target.Copy(zone());
2167 
2168   ProcessCallOrConstructRecursive(callee, new_target, *arguments,
2169                                   speculation_mode, padding,
2170                                   &new_accumulator_hints);
2171   environment()->accumulator_hints() = new_accumulator_hints;
2172 }
2173 
ProcessCallOrConstructRecursive(Hints const & callee,base::Optional<Hints> new_target,const HintsVector & arguments,SpeculationMode speculation_mode,MissingArgumentsPolicy padding,Hints * result_hints)2174 void SerializerForBackgroundCompilation::ProcessCallOrConstructRecursive(
2175     Hints const& callee, base::Optional<Hints> new_target,
2176     const HintsVector& arguments, SpeculationMode speculation_mode,
2177     MissingArgumentsPolicy padding, Hints* result_hints) {
2178   // For JSCallReducer::ReduceJSCall and JSCallReducer::ReduceJSConstruct.
2179   for (auto constant : callee.constants()) {
2180     ProcessCalleeForCallOrConstruct(constant, new_target, arguments,
2181                                     speculation_mode, padding, result_hints);
2182   }
2183 
2184   // For JSCallReducer::ReduceJSCall and JSCallReducer::ReduceJSConstruct.
2185   for (auto hint : callee.virtual_closures()) {
2186     ProcessCalleeForCallOrConstruct(Callee(hint), new_target, arguments,
2187                                     speculation_mode, padding, result_hints);
2188   }
2189 
2190   for (auto hint : callee.virtual_bound_functions()) {
2191     HintsVector new_arguments = hint.bound_arguments;
2192     new_arguments.insert(new_arguments.end(), arguments.begin(),
2193                          arguments.end());
2194     ProcessCallOrConstructRecursive(hint.bound_target, new_target,
2195                                     new_arguments, speculation_mode, padding,
2196                                     result_hints);
2197   }
2198 }
2199 
ProcessNewTargetForConstruct(Hints const & new_target_hints,Hints * result_hints)2200 void SerializerForBackgroundCompilation::ProcessNewTargetForConstruct(
2201     Hints const& new_target_hints, Hints* result_hints) {
2202   for (Handle<Object> target : new_target_hints.constants()) {
2203     if (target->IsJSBoundFunction()) {
2204       // Unroll the bound function.
2205       while (target->IsJSBoundFunction()) {
2206         target = handle(
2207             Handle<JSBoundFunction>::cast(target)->bound_target_function(),
2208             broker()->isolate());
2209       }
2210     }
2211     if (target->IsJSFunction()) {
2212       Handle<JSFunction> new_target(Handle<JSFunction>::cast(target));
2213       if (new_target->has_prototype_slot(broker()->isolate()) &&
2214           new_target->has_initial_map()) {
2215         result_hints->AddMap(
2216             handle(new_target->initial_map(), broker()->isolate()), zone(),
2217             broker());
2218       }
2219     }
2220   }
2221 
2222   for (auto const& virtual_bound_function :
2223        new_target_hints.virtual_bound_functions()) {
2224     ProcessNewTargetForConstruct(virtual_bound_function.bound_target,
2225                                  result_hints);
2226   }
2227 }
2228 
ProcessCallVarArgs(ConvertReceiverMode receiver_mode,Hints const & callee,interpreter::Register first_reg,int reg_count,FeedbackSlot slot,MissingArgumentsPolicy padding)2229 void SerializerForBackgroundCompilation::ProcessCallVarArgs(
2230     ConvertReceiverMode receiver_mode, Hints const& callee,
2231     interpreter::Register first_reg, int reg_count, FeedbackSlot slot,
2232     MissingArgumentsPolicy padding) {
2233   HintsVector args = PrepareArgumentsHints(first_reg, reg_count);
2234   // The receiver is either given in the first register or it is implicitly
2235   // the {undefined} value.
2236   if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
2237     args.insert(args.begin(),
2238                 Hints::SingleConstant(
2239                     broker()->isolate()->factory()->undefined_value(), zone()));
2240   }
2241   ProcessCallOrConstruct(callee, base::nullopt, &args, slot, padding);
2242 }
2243 
ProcessApiCall(Handle<SharedFunctionInfo> target,const HintsVector & arguments)2244 void SerializerForBackgroundCompilation::ProcessApiCall(
2245     Handle<SharedFunctionInfo> target, const HintsVector& arguments) {
2246   ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
2247                           Builtins::kCallFunctionTemplate_CheckAccess));
2248   ObjectRef(broker(),
2249             broker()->isolate()->builtins()->builtin_handle(
2250                 Builtins::kCallFunctionTemplate_CheckCompatibleReceiver));
2251   ObjectRef(
2252       broker(),
2253       broker()->isolate()->builtins()->builtin_handle(
2254           Builtins::kCallFunctionTemplate_CheckAccessAndCompatibleReceiver));
2255 
2256   FunctionTemplateInfoRef target_template_info(
2257       broker(),
2258       handle(target->function_data(kAcquireLoad), broker()->isolate()));
2259   if (!target_template_info.has_call_code()) return;
2260   target_template_info.SerializeCallCode();
2261 
2262   SharedFunctionInfoRef target_ref(broker(), target);
2263   target_ref.SerializeFunctionTemplateInfo();
2264 
2265   if (target_template_info.accept_any_receiver() &&
2266       target_template_info.is_signature_undefined()) {
2267     return;
2268   }
2269 
2270   if (arguments.empty()) return;
2271   Hints const& receiver_hints = arguments[0];
2272   for (auto hint : receiver_hints.constants()) {
2273     if (hint->IsUndefined()) {
2274       // The receiver is the global proxy.
2275       Handle<JSGlobalProxy> global_proxy =
2276           broker()->target_native_context().global_proxy_object().object();
2277       ProcessReceiverMapForApiCall(
2278           target_template_info,
2279           handle(global_proxy->map(), broker()->isolate()));
2280       continue;
2281     }
2282 
2283     if (!hint->IsJSReceiver()) continue;
2284     Handle<JSReceiver> receiver(Handle<JSReceiver>::cast(hint));
2285 
2286     ProcessReceiverMapForApiCall(target_template_info,
2287                                  handle(receiver->map(), broker()->isolate()));
2288   }
2289 
2290   for (auto receiver_map : receiver_hints.maps()) {
2291     ProcessReceiverMapForApiCall(target_template_info, receiver_map);
2292   }
2293 }
2294 
ProcessReceiverMapForApiCall(FunctionTemplateInfoRef target,Handle<Map> receiver)2295 void SerializerForBackgroundCompilation::ProcessReceiverMapForApiCall(
2296     FunctionTemplateInfoRef target, Handle<Map> receiver) {
2297   if (!receiver->is_access_check_needed()) {
2298     MapRef receiver_map(broker(), receiver);
2299     TRACE_BROKER(broker(), "Serializing holder for target: " << target);
2300     target.LookupHolderOfExpectedType(receiver_map,
2301                                       SerializationPolicy::kSerializeIfNeeded);
2302   }
2303 }
2304 
ProcessHintsForObjectCreate(Hints const & prototype)2305 void SerializerForBackgroundCompilation::ProcessHintsForObjectCreate(
2306     Hints const& prototype) {
2307   for (Handle<Object> constant_handle : prototype.constants()) {
2308     ObjectRef constant(broker(), constant_handle);
2309     if (constant.IsJSObject()) constant.AsJSObject().SerializeObjectCreateMap();
2310   }
2311 }
2312 
ProcessBuiltinCall(Handle<SharedFunctionInfo> target,base::Optional<Hints> new_target,const HintsVector & arguments,SpeculationMode speculation_mode,MissingArgumentsPolicy padding,Hints * result_hints)2313 void SerializerForBackgroundCompilation::ProcessBuiltinCall(
2314     Handle<SharedFunctionInfo> target, base::Optional<Hints> new_target,
2315     const HintsVector& arguments, SpeculationMode speculation_mode,
2316     MissingArgumentsPolicy padding, Hints* result_hints) {
2317   DCHECK(target->HasBuiltinId());
2318   const int builtin_id = target->builtin_id();
2319   const char* name = Builtins::name(builtin_id);
2320   TRACE_BROKER(broker(), "Serializing for call to builtin " << name);
2321   switch (builtin_id) {
2322     case Builtins::kObjectCreate: {
2323       if (arguments.size() >= 2) {
2324         ProcessHintsForObjectCreate(arguments[1]);
2325       } else {
2326         ProcessHintsForObjectCreate(Hints::SingleConstant(
2327             broker()->isolate()->factory()->undefined_value(), zone()));
2328       }
2329       break;
2330     }
2331     case Builtins::kPromisePrototypeCatch: {
2332       // For JSCallReducer::ReducePromisePrototypeCatch.
2333       if (speculation_mode != SpeculationMode::kDisallowSpeculation) {
2334         if (arguments.size() >= 1) {
2335           ProcessMapHintsForPromises(arguments[0]);
2336         }
2337       }
2338       break;
2339     }
2340     case Builtins::kPromisePrototypeFinally: {
2341       // For JSCallReducer::ReducePromisePrototypeFinally.
2342       if (speculation_mode != SpeculationMode::kDisallowSpeculation) {
2343         if (arguments.size() >= 1) {
2344           ProcessMapHintsForPromises(arguments[0]);
2345         }
2346         SharedFunctionInfoRef(
2347             broker(),
2348             broker()->isolate()->factory()->promise_catch_finally_shared_fun());
2349         SharedFunctionInfoRef(
2350             broker(),
2351             broker()->isolate()->factory()->promise_then_finally_shared_fun());
2352       }
2353       break;
2354     }
2355     case Builtins::kPromisePrototypeThen: {
2356       // For JSCallReducer::ReducePromisePrototypeThen.
2357       if (speculation_mode != SpeculationMode::kDisallowSpeculation) {
2358         if (arguments.size() >= 1) {
2359           ProcessMapHintsForPromises(arguments[0]);
2360         }
2361       }
2362       break;
2363     }
2364     case Builtins::kPromiseResolveTrampoline:
2365       // For JSCallReducer::ReducePromiseInternalResolve and
2366       // JSNativeContextSpecialization::ReduceJSResolvePromise.
2367       if (arguments.size() >= 1) {
2368         Hints const resolution_hints =
2369             arguments.size() >= 2
2370                 ? arguments[1]
2371                 : Hints::SingleConstant(
2372                       broker()->isolate()->factory()->undefined_value(),
2373                       zone());
2374         ProcessHintsForPromiseResolve(resolution_hints);
2375       }
2376       break;
2377     case Builtins::kRegExpPrototypeTest:
2378     case Builtins::kRegExpPrototypeTestFast:
2379       // For JSCallReducer::ReduceRegExpPrototypeTest.
2380       if (arguments.size() >= 1 &&
2381           speculation_mode != SpeculationMode::kDisallowSpeculation) {
2382         Hints const& regexp_hints = arguments[0];
2383         ProcessHintsForRegExpTest(regexp_hints);
2384       }
2385       break;
2386     case Builtins::kArrayEvery:
2387     case Builtins::kArrayFilter:
2388     case Builtins::kArrayForEach:
2389     case Builtins::kArrayPrototypeFind:
2390     case Builtins::kArrayPrototypeFindIndex:
2391     case Builtins::kArrayMap:
2392     case Builtins::kArraySome:
2393       if (arguments.size() >= 2 &&
2394           speculation_mode != SpeculationMode::kDisallowSpeculation) {
2395         Hints const& callback = arguments[1];
2396         // "Call(callbackfn, T, « kValue, k, O »)"
2397         HintsVector new_arguments(zone());
2398         new_arguments.push_back(
2399             arguments.size() < 3
2400                 ? Hints::SingleConstant(
2401                       broker()->isolate()->factory()->undefined_value(), zone())
2402                 : arguments[2]);                // T
2403         new_arguments.push_back(Hints());       // kValue
2404         new_arguments.push_back(Hints());       // k
2405         new_arguments.push_back(arguments[0]);  // O
2406         for (auto constant : callback.constants()) {
2407           ProcessCalleeForCallOrConstruct(
2408               constant, base::nullopt, new_arguments, speculation_mode,
2409               kMissingArgumentsAreUndefined, result_hints);
2410         }
2411         for (auto virtual_closure : callback.virtual_closures()) {
2412           ProcessCalleeForCallOrConstruct(
2413               Callee(virtual_closure), base::nullopt, new_arguments,
2414               speculation_mode, kMissingArgumentsAreUndefined, result_hints);
2415         }
2416       }
2417       break;
2418     case Builtins::kArrayReduce:
2419     case Builtins::kArrayReduceRight:
2420       if (arguments.size() >= 2 &&
2421           speculation_mode != SpeculationMode::kDisallowSpeculation) {
2422         Hints const& callback = arguments[1];
2423         // "Call(callbackfn, undefined, « accumulator, kValue, k, O »)"
2424         HintsVector new_arguments(zone());
2425         new_arguments.push_back(Hints::SingleConstant(
2426             broker()->isolate()->factory()->undefined_value(), zone()));
2427         new_arguments.push_back(Hints());       // accumulator
2428         new_arguments.push_back(Hints());       // kValue
2429         new_arguments.push_back(Hints());       // k
2430         new_arguments.push_back(arguments[0]);  // O
2431         for (auto constant : callback.constants()) {
2432           ProcessCalleeForCallOrConstruct(
2433               constant, base::nullopt, new_arguments, speculation_mode,
2434               kMissingArgumentsAreUndefined, result_hints);
2435         }
2436         for (auto virtual_closure : callback.virtual_closures()) {
2437           ProcessCalleeForCallOrConstruct(
2438               Callee(virtual_closure), base::nullopt, new_arguments,
2439               speculation_mode, kMissingArgumentsAreUndefined, result_hints);
2440         }
2441       }
2442       break;
2443     case Builtins::kFunctionPrototypeApply:
2444       if (arguments.size() >= 1) {
2445         // Drop hints for all arguments except the user-given receiver.
2446         Hints const new_receiver =
2447             arguments.size() >= 2
2448                 ? arguments[1]
2449                 : Hints::SingleConstant(
2450                       broker()->isolate()->factory()->undefined_value(),
2451                       zone());
2452         HintsVector new_arguments({new_receiver}, zone());
2453         for (auto constant : arguments[0].constants()) {
2454           ProcessCalleeForCallOrConstruct(
2455               constant, base::nullopt, new_arguments, speculation_mode,
2456               kMissingArgumentsAreUnknown, result_hints);
2457         }
2458         for (auto const& virtual_closure : arguments[0].virtual_closures()) {
2459           ProcessCalleeForCallOrConstruct(
2460               Callee(virtual_closure), base::nullopt, new_arguments,
2461               speculation_mode, kMissingArgumentsAreUnknown, result_hints);
2462         }
2463       }
2464       break;
2465     case Builtins::kPromiseConstructor:
2466       if (arguments.size() >= 1) {
2467         // "Call(executor, undefined, « resolvingFunctions.[[Resolve]],
2468         //                              resolvingFunctions.[[Reject]] »)"
2469         HintsVector new_arguments(
2470             {Hints::SingleConstant(
2471                 broker()->isolate()->factory()->undefined_value(), zone())},
2472             zone());
2473         for (auto constant : arguments[0].constants()) {
2474           ProcessCalleeForCallOrConstruct(
2475               constant, base::nullopt, new_arguments,
2476               SpeculationMode::kDisallowSpeculation,
2477               kMissingArgumentsAreUnknown, result_hints);
2478         }
2479         for (auto const& virtual_closure : arguments[0].virtual_closures()) {
2480           ProcessCalleeForCallOrConstruct(
2481               Callee(virtual_closure), base::nullopt, new_arguments,
2482               SpeculationMode::kDisallowSpeculation,
2483               kMissingArgumentsAreUnknown, result_hints);
2484         }
2485       }
2486       SharedFunctionInfoRef(
2487           broker(), broker()
2488                         ->isolate()
2489                         ->factory()
2490                         ->promise_capability_default_reject_shared_fun());
2491       SharedFunctionInfoRef(
2492           broker(), broker()
2493                         ->isolate()
2494                         ->factory()
2495                         ->promise_capability_default_resolve_shared_fun());
2496 
2497       break;
2498     case Builtins::kFunctionPrototypeCall:
2499       if (arguments.size() >= 1) {
2500         HintsVector new_arguments(arguments.begin() + 1, arguments.end(),
2501                                   zone());
2502         for (auto constant : arguments[0].constants()) {
2503           ProcessCalleeForCallOrConstruct(constant, base::nullopt,
2504                                           new_arguments, speculation_mode,
2505                                           padding, result_hints);
2506         }
2507         for (auto const& virtual_closure : arguments[0].virtual_closures()) {
2508           ProcessCalleeForCallOrConstruct(
2509               Callee(virtual_closure), base::nullopt, new_arguments,
2510               speculation_mode, padding, result_hints);
2511         }
2512       }
2513       break;
2514     case Builtins::kReflectApply:
2515     case Builtins::kReflectConstruct:
2516       if (arguments.size() >= 2) {
2517         for (auto constant : arguments[1].constants()) {
2518           if (constant->IsJSFunction()) {
2519             JSFunctionRef(broker(), constant).Serialize();
2520           }
2521         }
2522       }
2523       break;
2524     case Builtins::kObjectPrototypeIsPrototypeOf:
2525       if (arguments.size() >= 2) {
2526         ProcessHintsForHasInPrototypeChain(arguments[1]);
2527       }
2528       break;
2529     case Builtins::kFunctionPrototypeHasInstance:
2530       // For JSCallReducer::ReduceFunctionPrototypeHasInstance.
2531       if (arguments.size() >= 2) {
2532         ProcessHintsForOrdinaryHasInstance(arguments[0], arguments[1]);
2533       }
2534       break;
2535     case Builtins::kFastFunctionPrototypeBind:
2536       if (arguments.size() >= 1 &&
2537           speculation_mode != SpeculationMode::kDisallowSpeculation) {
2538         Hints const& bound_target = arguments[0];
2539         ProcessHintsForFunctionBind(bound_target);
2540         HintsVector new_arguments(arguments.begin() + 1, arguments.end(),
2541                                   zone());
2542         result_hints->AddVirtualBoundFunction(
2543             VirtualBoundFunction(bound_target, new_arguments), zone(),
2544             broker());
2545       }
2546       break;
2547     case Builtins::kObjectGetPrototypeOf:
2548     case Builtins::kReflectGetPrototypeOf:
2549       if (arguments.size() >= 2) {
2550         ProcessHintsForObjectGetPrototype(arguments[1]);
2551       } else {
2552         Hints const undefined_hint = Hints::SingleConstant(
2553             broker()->isolate()->factory()->undefined_value(), zone());
2554         ProcessHintsForObjectGetPrototype(undefined_hint);
2555       }
2556       break;
2557     case Builtins::kObjectPrototypeGetProto:
2558       if (arguments.size() >= 1) {
2559         ProcessHintsForObjectGetPrototype(arguments[0]);
2560       }
2561       break;
2562     case Builtins::kMapIteratorPrototypeNext:
2563       ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
2564                               Builtins::kOrderedHashTableHealIndex));
2565       ObjectRef(broker(),
2566                 broker()->isolate()->factory()->empty_ordered_hash_map());
2567       break;
2568     case Builtins::kSetIteratorPrototypeNext:
2569       ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
2570                               Builtins::kOrderedHashTableHealIndex));
2571       ObjectRef(broker(),
2572                 broker()->isolate()->factory()->empty_ordered_hash_set());
2573       break;
2574     default:
2575       break;
2576   }
2577 }
2578 
ProcessHintsForOrdinaryHasInstance(Hints const & constructor_hints,Hints const & instance_hints)2579 void SerializerForBackgroundCompilation::ProcessHintsForOrdinaryHasInstance(
2580     Hints const& constructor_hints, Hints const& instance_hints) {
2581   bool walk_prototypes = false;
2582   for (Handle<Object> constructor : constructor_hints.constants()) {
2583     // For JSNativeContextSpecialization::ReduceJSOrdinaryHasInstance.
2584     if (constructor->IsHeapObject()) {
2585       ProcessConstantForOrdinaryHasInstance(
2586           HeapObjectRef(broker(), constructor), &walk_prototypes);
2587     }
2588   }
2589   // For JSNativeContextSpecialization::ReduceJSHasInPrototypeChain.
2590   if (walk_prototypes) ProcessHintsForHasInPrototypeChain(instance_hints);
2591 }
2592 
ProcessHintsForHasInPrototypeChain(Hints const & instance_hints)2593 void SerializerForBackgroundCompilation::ProcessHintsForHasInPrototypeChain(
2594     Hints const& instance_hints) {
2595   auto processMap = [&](Handle<Map> map_handle) {
2596     MapRef map(broker(), map_handle);
2597     while (map.IsJSObjectMap()) {
2598       map.SerializePrototype();
2599       map = map.prototype().map();
2600     }
2601   };
2602 
2603   for (auto hint : instance_hints.constants()) {
2604     if (!hint->IsHeapObject()) continue;
2605     Handle<HeapObject> object(Handle<HeapObject>::cast(hint));
2606     processMap(handle(object->map(), broker()->isolate()));
2607   }
2608   for (auto map_hint : instance_hints.maps()) {
2609     processMap(map_hint);
2610   }
2611 }
2612 
ProcessHintsForPromiseResolve(Hints const & resolution_hints)2613 void SerializerForBackgroundCompilation::ProcessHintsForPromiseResolve(
2614     Hints const& resolution_hints) {
2615   auto processMap = [&](Handle<Map> map) {
2616     broker()->GetPropertyAccessInfo(
2617         MapRef(broker(), map),
2618         NameRef(broker(), broker()->isolate()->factory()->then_string()),
2619         AccessMode::kLoad, dependencies(),
2620         SerializationPolicy::kSerializeIfNeeded);
2621   };
2622 
2623   for (auto hint : resolution_hints.constants()) {
2624     if (!hint->IsHeapObject()) continue;
2625     Handle<HeapObject> resolution(Handle<HeapObject>::cast(hint));
2626     processMap(handle(resolution->map(), broker()->isolate()));
2627   }
2628   for (auto map_hint : resolution_hints.maps()) {
2629     processMap(map_hint);
2630   }
2631 }
2632 
ProcessMapHintsForPromises(Hints const & receiver_hints)2633 void SerializerForBackgroundCompilation::ProcessMapHintsForPromises(
2634     Hints const& receiver_hints) {
2635   // We need to serialize the prototypes on each receiver map.
2636   for (auto constant : receiver_hints.constants()) {
2637     if (!constant->IsJSPromise()) continue;
2638     Handle<Map> map(Handle<HeapObject>::cast(constant)->map(),
2639                     broker()->isolate());
2640     MapRef(broker(), map).SerializePrototype();
2641   }
2642   for (auto map : receiver_hints.maps()) {
2643     if (!map->IsJSPromiseMap()) continue;
2644     MapRef(broker(), map).SerializePrototype();
2645   }
2646 }
2647 
ProcessMapForRegExpTest(MapRef map)2648 PropertyAccessInfo SerializerForBackgroundCompilation::ProcessMapForRegExpTest(
2649     MapRef map) {
2650   PropertyAccessInfo ai_exec = broker()->GetPropertyAccessInfo(
2651       map, NameRef(broker(), broker()->isolate()->factory()->exec_string()),
2652       AccessMode::kLoad, dependencies(),
2653       SerializationPolicy::kSerializeIfNeeded);
2654 
2655   Handle<JSObject> holder;
2656   if (ai_exec.IsDataConstant() && ai_exec.holder().ToHandle(&holder)) {
2657     // The property is on the prototype chain.
2658     JSObjectRef holder_ref(broker(), holder);
2659     holder_ref.GetOwnDataProperty(ai_exec.field_representation(),
2660                                   ai_exec.field_index(),
2661                                   SerializationPolicy::kSerializeIfNeeded);
2662   }
2663   return ai_exec;
2664 }
2665 
ProcessHintsForRegExpTest(Hints const & regexp_hints)2666 void SerializerForBackgroundCompilation::ProcessHintsForRegExpTest(
2667     Hints const& regexp_hints) {
2668   for (auto hint : regexp_hints.constants()) {
2669     if (!hint->IsJSRegExp()) continue;
2670     Handle<JSRegExp> regexp(Handle<JSRegExp>::cast(hint));
2671     Handle<Map> regexp_map(regexp->map(), broker()->isolate());
2672     PropertyAccessInfo ai_exec =
2673         ProcessMapForRegExpTest(MapRef(broker(), regexp_map));
2674     Handle<JSObject> holder;
2675     if (ai_exec.IsDataConstant() && !ai_exec.holder().ToHandle(&holder)) {
2676       // The property is on the object itself.
2677       JSObjectRef holder_ref(broker(), regexp);
2678       holder_ref.GetOwnDataProperty(ai_exec.field_representation(),
2679                                     ai_exec.field_index(),
2680                                     SerializationPolicy::kSerializeIfNeeded);
2681     }
2682   }
2683 
2684   for (auto map : regexp_hints.maps()) {
2685     if (!map->IsJSRegExpMap()) continue;
2686     ProcessMapForRegExpTest(MapRef(broker(), map));
2687   }
2688 }
2689 
2690 namespace {
ProcessMapForFunctionBind(MapRef map)2691 void ProcessMapForFunctionBind(MapRef map) {
2692   map.SerializePrototype();
2693   int min_nof_descriptors = std::max({JSFunction::kLengthDescriptorIndex,
2694                                       JSFunction::kNameDescriptorIndex}) +
2695                             1;
2696   if (map.NumberOfOwnDescriptors() >= min_nof_descriptors) {
2697     map.SerializeOwnDescriptor(
2698         InternalIndex(JSFunction::kLengthDescriptorIndex));
2699     map.SerializeOwnDescriptor(InternalIndex(JSFunction::kNameDescriptorIndex));
2700   }
2701 }
2702 }  // namespace
2703 
ProcessHintsForFunctionBind(Hints const & receiver_hints)2704 void SerializerForBackgroundCompilation::ProcessHintsForFunctionBind(
2705     Hints const& receiver_hints) {
2706   for (auto constant : receiver_hints.constants()) {
2707     if (!constant->IsJSFunction()) continue;
2708     JSFunctionRef function(broker(), constant);
2709     function.Serialize();
2710     ProcessMapForFunctionBind(function.map());
2711   }
2712 
2713   for (auto map : receiver_hints.maps()) {
2714     if (!map->IsJSFunctionMap()) continue;
2715     MapRef map_ref(broker(), map);
2716     ProcessMapForFunctionBind(map_ref);
2717   }
2718 }
2719 
ProcessHintsForObjectGetPrototype(Hints const & object_hints)2720 void SerializerForBackgroundCompilation::ProcessHintsForObjectGetPrototype(
2721     Hints const& object_hints) {
2722   for (auto constant : object_hints.constants()) {
2723     if (!constant->IsHeapObject()) continue;
2724     HeapObjectRef object(broker(), constant);
2725     object.map().SerializePrototype();
2726   }
2727 
2728   for (auto map : object_hints.maps()) {
2729     MapRef map_ref(broker(), map);
2730     map_ref.SerializePrototype();
2731   }
2732 }
2733 
ContributeToJumpTargetEnvironment(int target_offset)2734 void SerializerForBackgroundCompilation::ContributeToJumpTargetEnvironment(
2735     int target_offset) {
2736   auto it = jump_target_environments_.find(target_offset);
2737   if (it == jump_target_environments_.end()) {
2738     jump_target_environments_[target_offset] =
2739         zone()->New<Environment>(*environment());
2740   } else {
2741     it->second->Merge(environment(), zone(), broker());
2742   }
2743 }
2744 
IncorporateJumpTargetEnvironment(int target_offset)2745 void SerializerForBackgroundCompilation::IncorporateJumpTargetEnvironment(
2746     int target_offset) {
2747   auto it = jump_target_environments_.find(target_offset);
2748   if (it != jump_target_environments_.end()) {
2749     environment()->Merge(it->second, zone(), broker());
2750     jump_target_environments_.erase(it);
2751   }
2752 }
2753 
ProcessJump(interpreter::BytecodeArrayIterator * iterator)2754 void SerializerForBackgroundCompilation::ProcessJump(
2755     interpreter::BytecodeArrayIterator* iterator) {
2756   int jump_target = iterator->GetJumpTargetOffset();
2757   if (iterator->current_offset() < jump_target) {
2758     ContributeToJumpTargetEnvironment(jump_target);
2759   }
2760 }
2761 
VisitReturn(BytecodeArrayIterator * iterator)2762 void SerializerForBackgroundCompilation::VisitReturn(
2763     BytecodeArrayIterator* iterator) {
2764   return_value_hints().Add(environment()->accumulator_hints(), zone(),
2765                            broker());
2766   environment()->Kill();
2767 }
2768 
VisitSwitchOnSmiNoFeedback(interpreter::BytecodeArrayIterator * iterator)2769 void SerializerForBackgroundCompilation::VisitSwitchOnSmiNoFeedback(
2770     interpreter::BytecodeArrayIterator* iterator) {
2771   interpreter::JumpTableTargetOffsets targets =
2772       iterator->GetJumpTableTargetOffsets();
2773   for (const auto& target : targets) {
2774     ContributeToJumpTargetEnvironment(target.target_offset);
2775   }
2776 }
2777 
VisitSwitchOnGeneratorState(interpreter::BytecodeArrayIterator * iterator)2778 void SerializerForBackgroundCompilation::VisitSwitchOnGeneratorState(
2779     interpreter::BytecodeArrayIterator* iterator) {
2780   for (const auto& target : GetBytecodeAnalysis().resume_jump_targets()) {
2781     ContributeToJumpTargetEnvironment(target.target_offset());
2782   }
2783 }
2784 
VisitConstruct(BytecodeArrayIterator * iterator)2785 void SerializerForBackgroundCompilation::VisitConstruct(
2786     BytecodeArrayIterator* iterator) {
2787   Hints& new_target = environment()->accumulator_hints();
2788   Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
2789   interpreter::Register first_reg = iterator->GetRegisterOperand(1);
2790   size_t reg_count = iterator->GetRegisterCountOperand(2);
2791   FeedbackSlot slot = iterator->GetSlotOperand(3);
2792 
2793   HintsVector args = PrepareArgumentsHints(first_reg, reg_count);
2794 
2795   ProcessCallOrConstruct(callee, new_target, &args, slot,
2796                          kMissingArgumentsAreUndefined);
2797 }
2798 
VisitConstructWithSpread(BytecodeArrayIterator * iterator)2799 void SerializerForBackgroundCompilation::VisitConstructWithSpread(
2800     BytecodeArrayIterator* iterator) {
2801   Hints const& new_target = environment()->accumulator_hints();
2802   Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
2803   interpreter::Register first_reg = iterator->GetRegisterOperand(1);
2804   size_t reg_count = iterator->GetRegisterCountOperand(2);
2805   FeedbackSlot slot = iterator->GetSlotOperand(3);
2806 
2807   DCHECK_GT(reg_count, 0);
2808   reg_count--;  // Pop the spread element.
2809   HintsVector args = PrepareArgumentsHints(first_reg, reg_count);
2810 
2811   ProcessCallOrConstruct(callee, new_target, &args, slot,
2812                          kMissingArgumentsAreUnknown);
2813 }
2814 
ProcessGlobalAccess(FeedbackSlot slot,bool is_load)2815 void SerializerForBackgroundCompilation::ProcessGlobalAccess(FeedbackSlot slot,
2816                                                              bool is_load) {
2817   if (slot.IsInvalid() || feedback_vector().is_null()) return;
2818   FeedbackSource source(feedback_vector(), slot);
2819   ProcessedFeedback const& feedback =
2820       broker()->ProcessFeedbackForGlobalAccess(source);
2821 
2822   if (is_load) {
2823     Hints result_hints;
2824     if (feedback.kind() == ProcessedFeedback::kGlobalAccess) {
2825       // We may be able to contribute to accumulator constant hints.
2826       base::Optional<ObjectRef> value =
2827           feedback.AsGlobalAccess().GetConstantHint();
2828       if (value.has_value()) {
2829         result_hints.AddConstant(value->object(), zone(), broker());
2830       }
2831     } else {
2832       DCHECK(feedback.IsInsufficient());
2833     }
2834     environment()->accumulator_hints() = result_hints;
2835   }
2836 }
2837 
VisitLdaGlobal(BytecodeArrayIterator * iterator)2838 void SerializerForBackgroundCompilation::VisitLdaGlobal(
2839     BytecodeArrayIterator* iterator) {
2840   NameRef(broker(),
2841           iterator->GetConstantForIndexOperand(0, broker()->isolate()));
2842   FeedbackSlot slot = iterator->GetSlotOperand(1);
2843   ProcessGlobalAccess(slot, true);
2844 }
2845 
VisitLdaGlobalInsideTypeof(BytecodeArrayIterator * iterator)2846 void SerializerForBackgroundCompilation::VisitLdaGlobalInsideTypeof(
2847     BytecodeArrayIterator* iterator) {
2848   VisitLdaGlobal(iterator);
2849 }
2850 
VisitLdaLookupSlot(BytecodeArrayIterator * iterator)2851 void SerializerForBackgroundCompilation::VisitLdaLookupSlot(
2852     BytecodeArrayIterator* iterator) {
2853   ObjectRef(broker(),
2854             iterator->GetConstantForIndexOperand(0, broker()->isolate()));
2855   environment()->accumulator_hints() = Hints();
2856 }
2857 
VisitLdaLookupSlotInsideTypeof(BytecodeArrayIterator * iterator)2858 void SerializerForBackgroundCompilation::VisitLdaLookupSlotInsideTypeof(
2859     BytecodeArrayIterator* iterator) {
2860   ObjectRef(broker(),
2861             iterator->GetConstantForIndexOperand(0, broker()->isolate()));
2862   environment()->accumulator_hints() = Hints();
2863 }
2864 
ProcessCheckContextExtensions(int depth)2865 void SerializerForBackgroundCompilation::ProcessCheckContextExtensions(
2866     int depth) {
2867   // for BytecodeGraphBuilder::CheckContextExtensions.
2868   Hints const& context_hints = environment()->current_context_hints();
2869   for (int i = 0; i < depth; i++) {
2870     ProcessContextAccess(context_hints, Context::EXTENSION_INDEX, i,
2871                          kSerializeSlot);
2872   }
2873   SharedFunctionInfoRef shared(broker(), function().shared());
2874   shared.SerializeScopeInfoChain();
2875 }
2876 
ProcessLdaLookupGlobalSlot(BytecodeArrayIterator * iterator)2877 void SerializerForBackgroundCompilation::ProcessLdaLookupGlobalSlot(
2878     BytecodeArrayIterator* iterator) {
2879   ProcessCheckContextExtensions(iterator->GetUnsignedImmediateOperand(2));
2880   // TODO(neis): BytecodeGraphBilder may insert a JSLoadGlobal.
2881   VisitLdaGlobal(iterator);
2882 }
2883 
VisitLdaLookupGlobalSlot(BytecodeArrayIterator * iterator)2884 void SerializerForBackgroundCompilation::VisitLdaLookupGlobalSlot(
2885     BytecodeArrayIterator* iterator) {
2886   ProcessLdaLookupGlobalSlot(iterator);
2887 }
2888 
VisitLdaLookupGlobalSlotInsideTypeof(BytecodeArrayIterator * iterator)2889 void SerializerForBackgroundCompilation::VisitLdaLookupGlobalSlotInsideTypeof(
2890     BytecodeArrayIterator* iterator) {
2891   ProcessLdaLookupGlobalSlot(iterator);
2892 }
2893 
VisitStaGlobal(BytecodeArrayIterator * iterator)2894 void SerializerForBackgroundCompilation::VisitStaGlobal(
2895     BytecodeArrayIterator* iterator) {
2896   NameRef(broker(),
2897           iterator->GetConstantForIndexOperand(0, broker()->isolate()));
2898   FeedbackSlot slot = iterator->GetSlotOperand(1);
2899   ProcessGlobalAccess(slot, false);
2900 }
2901 
ProcessLdaLookupContextSlot(BytecodeArrayIterator * iterator)2902 void SerializerForBackgroundCompilation::ProcessLdaLookupContextSlot(
2903     BytecodeArrayIterator* iterator) {
2904   const int slot_index = iterator->GetIndexOperand(1);
2905   const int depth = iterator->GetUnsignedImmediateOperand(2);
2906   NameRef(broker(),
2907           iterator->GetConstantForIndexOperand(0, broker()->isolate()));
2908   ProcessCheckContextExtensions(depth);
2909   environment()->accumulator_hints() = Hints();
2910   ProcessContextAccess(environment()->current_context_hints(), slot_index,
2911                        depth, kIgnoreSlot);
2912 }
2913 
VisitLdaLookupContextSlot(BytecodeArrayIterator * iterator)2914 void SerializerForBackgroundCompilation::VisitLdaLookupContextSlot(
2915     BytecodeArrayIterator* iterator) {
2916   ProcessLdaLookupContextSlot(iterator);
2917 }
2918 
VisitLdaLookupContextSlotInsideTypeof(BytecodeArrayIterator * iterator)2919 void SerializerForBackgroundCompilation::VisitLdaLookupContextSlotInsideTypeof(
2920     BytecodeArrayIterator* iterator) {
2921   ProcessLdaLookupContextSlot(iterator);
2922 }
2923 
2924 // TODO(neis): Avoid duplicating this.
2925 namespace {
2926 template <class MapContainer>
GetRelevantReceiverMaps(Isolate * isolate,MapContainer const & maps)2927 MapHandles GetRelevantReceiverMaps(Isolate* isolate, MapContainer const& maps) {
2928   MapHandles result;
2929   for (Handle<Map> map : maps) {
2930     if (Map::TryUpdate(isolate, map).ToHandle(&map) &&
2931         !map->is_abandoned_prototype_map()) {
2932       DCHECK(!map->is_deprecated());
2933       result.push_back(map);
2934     }
2935   }
2936   return result;
2937 }
2938 }  // namespace
2939 
ProcessCompareOperation(FeedbackSlot slot)2940 void SerializerForBackgroundCompilation::ProcessCompareOperation(
2941     FeedbackSlot slot) {
2942   if (slot.IsInvalid() || feedback_vector().is_null()) return;
2943   FeedbackSource source(function().feedback_vector(), slot);
2944   ProcessedFeedback const& feedback =
2945       broker()->ProcessFeedbackForCompareOperation(source);
2946   if (BailoutOnUninitialized(feedback)) return;
2947   environment()->accumulator_hints() = Hints();
2948 }
2949 
ProcessForIn(FeedbackSlot slot)2950 void SerializerForBackgroundCompilation::ProcessForIn(FeedbackSlot slot) {
2951   if (slot.IsInvalid() || feedback_vector().is_null()) return;
2952   FeedbackSource source(feedback_vector(), slot);
2953   ProcessedFeedback const& feedback = broker()->ProcessFeedbackForForIn(source);
2954   if (BailoutOnUninitialized(feedback)) return;
2955   environment()->accumulator_hints() = Hints();
2956 }
2957 
ProcessUnaryOrBinaryOperation(FeedbackSlot slot,bool honor_bailout_on_uninitialized)2958 void SerializerForBackgroundCompilation::ProcessUnaryOrBinaryOperation(
2959     FeedbackSlot slot, bool honor_bailout_on_uninitialized) {
2960   if (slot.IsInvalid() || feedback_vector().is_null()) return;
2961   FeedbackSource source(feedback_vector(), slot);
2962   // Internally V8 uses binary op feedback also for unary ops.
2963   ProcessedFeedback const& feedback =
2964       broker()->ProcessFeedbackForBinaryOperation(source);
2965   if (honor_bailout_on_uninitialized && BailoutOnUninitialized(feedback)) {
2966     return;
2967   }
2968   environment()->accumulator_hints() = Hints();
2969 }
2970 
2971 PropertyAccessInfo
ProcessMapForNamedPropertyAccess(Hints * receiver,base::Optional<MapRef> receiver_map,MapRef lookup_start_object_map,NameRef const & name,AccessMode access_mode,base::Optional<JSObjectRef> concrete_receiver,Hints * result_hints)2972 SerializerForBackgroundCompilation::ProcessMapForNamedPropertyAccess(
2973     Hints* receiver, base::Optional<MapRef> receiver_map,
2974     MapRef lookup_start_object_map, NameRef const& name, AccessMode access_mode,
2975     base::Optional<JSObjectRef> concrete_receiver, Hints* result_hints) {
2976   DCHECK_IMPLIES(concrete_receiver.has_value(), receiver_map.has_value());
2977 
2978   // For JSNativeContextSpecialization::InferRootMap
2979   lookup_start_object_map.SerializeRootMap();
2980 
2981   // For JSNativeContextSpecialization::ReduceNamedAccess.
2982   JSGlobalProxyRef global_proxy =
2983       broker()->target_native_context().global_proxy_object();
2984   JSGlobalObjectRef global_object =
2985       broker()->target_native_context().global_object();
2986   if (lookup_start_object_map.equals(global_proxy.map())) {
2987     base::Optional<PropertyCellRef> cell = global_object.GetPropertyCell(
2988         name, SerializationPolicy::kSerializeIfNeeded);
2989     if (access_mode == AccessMode::kLoad && cell.has_value()) {
2990       result_hints->AddConstant(cell->value().object(), zone(), broker());
2991     }
2992   }
2993 
2994   PropertyAccessInfo access_info = broker()->GetPropertyAccessInfo(
2995       lookup_start_object_map, name, access_mode, dependencies(),
2996       SerializationPolicy::kSerializeIfNeeded);
2997 
2998   // For JSNativeContextSpecialization::InlinePropertySetterCall
2999   // and InlinePropertyGetterCall.
3000   if (access_info.IsAccessorConstant() && !access_info.constant().is_null()) {
3001     if (access_info.constant()->IsJSFunction()) {
3002       JSFunctionRef function(broker(), access_info.constant());
3003 
3004       if (receiver_map.has_value()) {
3005         // For JSCallReducer and JSInlining(Heuristic).
3006         HintsVector arguments(
3007             {Hints::SingleMap(receiver_map->object(), zone())}, zone());
3008         // In the case of a setter any added result hints won't make sense, but
3009         // they will be ignored anyways by Process*PropertyAccess due to the
3010         // access mode not being kLoad.
3011         ProcessCalleeForCallOrConstruct(
3012             function.object(), base::nullopt, arguments,
3013             SpeculationMode::kDisallowSpeculation,
3014             kMissingArgumentsAreUndefined, result_hints);
3015 
3016         // For JSCallReducer::ReduceCallApiFunction.
3017         Handle<SharedFunctionInfo> sfi = function.shared().object();
3018         if (sfi->IsApiFunction()) {
3019           FunctionTemplateInfoRef fti_ref(
3020               broker(), handle(sfi->get_api_func_data(), broker()->isolate()));
3021           if (fti_ref.has_call_code()) {
3022             fti_ref.SerializeCallCode();
3023             ProcessReceiverMapForApiCall(fti_ref, receiver_map->object());
3024           }
3025         }
3026       }
3027     } else if (access_info.constant()->IsJSBoundFunction()) {
3028       JSBoundFunctionRef function(broker(), access_info.constant());
3029 
3030       // For JSCallReducer::ReduceJSCall.
3031       function.Serialize();
3032     } else {
3033       FunctionTemplateInfoRef fti(broker(), access_info.constant());
3034       if (fti.has_call_code()) fti.SerializeCallCode();
3035     }
3036   } else if (access_info.IsModuleExport()) {
3037     // For JSNativeContextSpecialization::BuildPropertyLoad
3038     DCHECK(!access_info.constant().is_null());
3039     CellRef(broker(), access_info.constant());
3040   }
3041 
3042   switch (access_mode) {
3043     case AccessMode::kLoad:
3044       // For PropertyAccessBuilder::TryBuildLoadConstantDataField
3045       if (access_info.IsDataConstant()) {
3046         base::Optional<JSObjectRef> holder;
3047         Handle<JSObject> prototype;
3048         if (access_info.holder().ToHandle(&prototype)) {
3049           holder = JSObjectRef(broker(), prototype);
3050         } else {
3051           CHECK_IMPLIES(concrete_receiver.has_value(),
3052                         concrete_receiver->map().equals(*receiver_map));
3053           holder = concrete_receiver;
3054         }
3055 
3056         if (holder.has_value()) {
3057           base::Optional<ObjectRef> constant(holder->GetOwnDataProperty(
3058               access_info.field_representation(), access_info.field_index(),
3059               SerializationPolicy::kSerializeIfNeeded));
3060           if (constant.has_value()) {
3061             result_hints->AddConstant(constant->object(), zone(), broker());
3062           }
3063         }
3064       }
3065       break;
3066     case AccessMode::kStore:
3067     case AccessMode::kStoreInLiteral:
3068       // For MapInference (StoreField case).
3069       if (access_info.IsDataField() || access_info.IsDataConstant()) {
3070         Handle<Map> transition_map;
3071         if (access_info.transition_map().ToHandle(&transition_map)) {
3072           MapRef map_ref(broker(), transition_map);
3073           TRACE_BROKER(broker(), "Propagating transition map "
3074                                      << map_ref << " to receiver hints.");
3075           receiver->AddMap(transition_map, zone(), broker_, false);
3076         }
3077       }
3078       break;
3079     case AccessMode::kHas:
3080       break;
3081   }
3082 
3083   return access_info;
3084 }
3085 
ProcessMinimorphicPropertyAccess(MinimorphicLoadPropertyAccessFeedback const & feedback,FeedbackSource const & source)3086 void SerializerForBackgroundCompilation::ProcessMinimorphicPropertyAccess(
3087     MinimorphicLoadPropertyAccessFeedback const& feedback,
3088     FeedbackSource const& source) {
3089   broker()->GetPropertyAccessInfo(feedback, source,
3090                                   SerializationPolicy::kSerializeIfNeeded);
3091 }
3092 
VisitLdaKeyedProperty(BytecodeArrayIterator * iterator)3093 void SerializerForBackgroundCompilation::VisitLdaKeyedProperty(
3094     BytecodeArrayIterator* iterator) {
3095   Hints const& key = environment()->accumulator_hints();
3096   Hints* receiver = &register_hints(iterator->GetRegisterOperand(0));
3097   FeedbackSlot slot = iterator->GetSlotOperand(1);
3098   ProcessKeyedPropertyAccess(receiver, key, slot, AccessMode::kLoad, true);
3099 }
3100 
ProcessKeyedPropertyAccess(Hints * receiver,Hints const & key,FeedbackSlot slot,AccessMode access_mode,bool honor_bailout_on_uninitialized)3101 void SerializerForBackgroundCompilation::ProcessKeyedPropertyAccess(
3102     Hints* receiver, Hints const& key, FeedbackSlot slot,
3103     AccessMode access_mode, bool honor_bailout_on_uninitialized) {
3104   if (slot.IsInvalid() || feedback_vector().is_null()) return;
3105   FeedbackSource source(feedback_vector(), slot);
3106   ProcessedFeedback const& feedback =
3107       broker()->ProcessFeedbackForPropertyAccess(source, access_mode,
3108                                                  base::nullopt);
3109   if (honor_bailout_on_uninitialized && BailoutOnUninitialized(feedback)) {
3110     return;
3111   }
3112 
3113   Hints new_accumulator_hints;
3114   switch (feedback.kind()) {
3115     case ProcessedFeedback::kElementAccess:
3116       ProcessElementAccess(*receiver, key, feedback.AsElementAccess(),
3117                            access_mode);
3118       break;
3119     case ProcessedFeedback::kNamedAccess:
3120       ProcessNamedAccess(receiver, feedback.AsNamedAccess(), access_mode,
3121                          &new_accumulator_hints);
3122       break;
3123     case ProcessedFeedback::kInsufficient:
3124       break;
3125     default:
3126       UNREACHABLE();
3127   }
3128 
3129   if (access_mode == AccessMode::kLoad) {
3130     environment()->accumulator_hints() = new_accumulator_hints;
3131   }
3132 }
3133 
ProcessNamedPropertyAccess(Hints * receiver,NameRef const & name,FeedbackSlot slot,AccessMode access_mode)3134 void SerializerForBackgroundCompilation::ProcessNamedPropertyAccess(
3135     Hints* receiver, NameRef const& name, FeedbackSlot slot,
3136     AccessMode access_mode) {
3137   if (slot.IsInvalid() || feedback_vector().is_null()) return;
3138   FeedbackSource source(feedback_vector(), slot);
3139   ProcessedFeedback const& feedback =
3140       broker()->ProcessFeedbackForPropertyAccess(source, access_mode, name);
3141   if (BailoutOnUninitialized(feedback)) return;
3142 
3143   Hints new_accumulator_hints;
3144   switch (feedback.kind()) {
3145     case ProcessedFeedback::kNamedAccess:
3146       DCHECK(name.equals(feedback.AsNamedAccess().name()));
3147       ProcessNamedAccess(receiver, feedback.AsNamedAccess(), access_mode,
3148                          &new_accumulator_hints);
3149       break;
3150     case ProcessedFeedback::kMinimorphicPropertyAccess:
3151       DCHECK(name.equals(feedback.AsMinimorphicPropertyAccess().name()));
3152       ProcessMinimorphicPropertyAccess(feedback.AsMinimorphicPropertyAccess(),
3153                                        source);
3154       break;
3155     case ProcessedFeedback::kInsufficient:
3156       break;
3157     default:
3158       UNREACHABLE();
3159   }
3160 
3161   if (access_mode == AccessMode::kLoad) {
3162     environment()->accumulator_hints() = new_accumulator_hints;
3163   }
3164 }
3165 
ProcessNamedSuperPropertyAccess(Hints * receiver,NameRef const & name,FeedbackSlot slot,AccessMode access_mode)3166 void SerializerForBackgroundCompilation::ProcessNamedSuperPropertyAccess(
3167     Hints* receiver, NameRef const& name, FeedbackSlot slot,
3168     AccessMode access_mode) {
3169   if (slot.IsInvalid() || feedback_vector().is_null()) return;
3170   FeedbackSource source(feedback_vector(), slot);
3171   ProcessedFeedback const& feedback =
3172       broker()->ProcessFeedbackForPropertyAccess(source, access_mode, name);
3173   if (BailoutOnUninitialized(feedback)) return;
3174 
3175   Hints new_accumulator_hints;
3176   switch (feedback.kind()) {
3177     case ProcessedFeedback::kNamedAccess:
3178       DCHECK(name.equals(feedback.AsNamedAccess().name()));
3179       ProcessNamedSuperAccess(receiver, feedback.AsNamedAccess(), access_mode,
3180                               &new_accumulator_hints);
3181       break;
3182     case ProcessedFeedback::kMinimorphicPropertyAccess:
3183       DCHECK(name.equals(feedback.AsMinimorphicPropertyAccess().name()));
3184       ProcessMinimorphicPropertyAccess(feedback.AsMinimorphicPropertyAccess(),
3185                                        source);
3186       break;
3187     case ProcessedFeedback::kInsufficient:
3188       break;
3189     default:
3190       UNREACHABLE();
3191   }
3192 
3193   if (access_mode == AccessMode::kLoad) {
3194     environment()->accumulator_hints() = new_accumulator_hints;
3195   }
3196 }
3197 
ProcessNamedAccess(Hints * receiver,NamedAccessFeedback const & feedback,AccessMode access_mode,Hints * result_hints)3198 void SerializerForBackgroundCompilation::ProcessNamedAccess(
3199     Hints* receiver, NamedAccessFeedback const& feedback,
3200     AccessMode access_mode, Hints* result_hints) {
3201   for (Handle<Map> map : feedback.maps()) {
3202     MapRef map_ref(broker(), map);
3203     TRACE_BROKER(broker(), "Propagating feedback map "
3204                                << map_ref << " to receiver hints.");
3205     receiver->AddMap(map, zone(), broker_, false);
3206   }
3207 
3208   for (Handle<Map> map :
3209        GetRelevantReceiverMaps(broker()->isolate(), receiver->maps())) {
3210     MapRef map_ref(broker(), map);
3211     ProcessMapForNamedPropertyAccess(receiver, map_ref, map_ref,
3212                                      feedback.name(), access_mode,
3213                                      base::nullopt, result_hints);
3214   }
3215 
3216   for (Handle<Object> hint : receiver->constants()) {
3217     ObjectRef object(broker(), hint);
3218     if (access_mode == AccessMode::kLoad && object.IsJSObject()) {
3219       MapRef map_ref = object.AsJSObject().map();
3220       ProcessMapForNamedPropertyAccess(receiver, map_ref, map_ref,
3221                                        feedback.name(), access_mode,
3222                                        object.AsJSObject(), result_hints);
3223     }
3224     // For JSNativeContextSpecialization::ReduceJSLoadNamed.
3225     if (access_mode == AccessMode::kLoad && object.IsJSFunction() &&
3226         feedback.name().equals(ObjectRef(
3227             broker(), broker()->isolate()->factory()->prototype_string()))) {
3228       JSFunctionRef function = object.AsJSFunction();
3229       function.Serialize();
3230       if (result_hints != nullptr && function.has_prototype()) {
3231         result_hints->AddConstant(function.prototype().object(), zone(),
3232                                   broker());
3233       }
3234     }
3235     // TODO(neis): Also record accumulator hint for string.length and maybe
3236     // more?
3237   }
3238 }
3239 
ProcessNamedSuperAccess(Hints * receiver,NamedAccessFeedback const & feedback,AccessMode access_mode,Hints * result_hints)3240 void SerializerForBackgroundCompilation::ProcessNamedSuperAccess(
3241     Hints* receiver, NamedAccessFeedback const& feedback,
3242     AccessMode access_mode, Hints* result_hints) {
3243   MapHandles receiver_maps =
3244       GetRelevantReceiverMaps(broker()->isolate(), receiver->maps());
3245   for (Handle<Map> receiver_map : receiver_maps) {
3246     MapRef receiver_map_ref(broker(), receiver_map);
3247     for (Handle<Map> feedback_map : feedback.maps()) {
3248       MapRef feedback_map_ref(broker(), feedback_map);
3249       ProcessMapForNamedPropertyAccess(
3250           receiver, receiver_map_ref, feedback_map_ref, feedback.name(),
3251           access_mode, base::nullopt, result_hints);
3252     }
3253   }
3254   if (receiver_maps.empty()) {
3255     for (Handle<Map> feedback_map : feedback.maps()) {
3256       MapRef feedback_map_ref(broker(), feedback_map);
3257       ProcessMapForNamedPropertyAccess(
3258           receiver, base::nullopt, feedback_map_ref, feedback.name(),
3259           access_mode, base::nullopt, result_hints);
3260     }
3261   }
3262 }
3263 
ProcessElementAccess(Hints const & receiver,Hints const & key,ElementAccessFeedback const & feedback,AccessMode access_mode)3264 void SerializerForBackgroundCompilation::ProcessElementAccess(
3265     Hints const& receiver, Hints const& key,
3266     ElementAccessFeedback const& feedback, AccessMode access_mode) {
3267   for (auto const& group : feedback.transition_groups()) {
3268     for (Handle<Map> map_handle : group) {
3269       MapRef map(broker(), map_handle);
3270       switch (access_mode) {
3271         case AccessMode::kHas:
3272         case AccessMode::kLoad:
3273           map.SerializeForElementLoad();
3274           break;
3275         case AccessMode::kStore:
3276           map.SerializeForElementStore();
3277           break;
3278         case AccessMode::kStoreInLiteral:
3279           // This operation is fairly local and simple, nothing to serialize.
3280           break;
3281       }
3282     }
3283   }
3284 
3285   for (Handle<Object> hint : receiver.constants()) {
3286     ObjectRef receiver_ref(broker(), hint);
3287 
3288     // For JSNativeContextSpecialization::InferRootMap
3289     if (receiver_ref.IsHeapObject()) {
3290       receiver_ref.AsHeapObject().map().SerializeRootMap();
3291     }
3292 
3293     // For JSNativeContextSpecialization::ReduceElementAccess.
3294     if (receiver_ref.IsJSTypedArray()) {
3295       receiver_ref.AsJSTypedArray().Serialize();
3296     }
3297 
3298     // For JSNativeContextSpecialization::ReduceElementLoadFromHeapConstant.
3299     if (access_mode == AccessMode::kLoad || access_mode == AccessMode::kHas) {
3300       for (Handle<Object> hint : key.constants()) {
3301         ObjectRef key_ref(broker(), hint);
3302         // TODO(neis): Do this for integer-HeapNumbers too?
3303         if (key_ref.IsSmi() && key_ref.AsSmi() >= 0) {
3304           base::Optional<ObjectRef> element =
3305               receiver_ref.GetOwnConstantElement(
3306                   key_ref.AsSmi(), SerializationPolicy::kSerializeIfNeeded);
3307           if (!element.has_value() && receiver_ref.IsJSArray()) {
3308             // We didn't find a constant element, but if the receiver is a
3309             // cow-array we can exploit the fact that any future write to the
3310             // element will replace the whole elements storage.
3311             receiver_ref.AsJSArray().GetOwnCowElement(
3312                 key_ref.AsSmi(), SerializationPolicy::kSerializeIfNeeded);
3313           }
3314         }
3315       }
3316     }
3317   }
3318 
3319   // For JSNativeContextSpecialization::InferRootMap
3320   for (Handle<Map> map : receiver.maps()) {
3321     MapRef map_ref(broker(), map);
3322     map_ref.SerializeRootMap();
3323   }
3324 }
3325 
VisitLdaNamedProperty(BytecodeArrayIterator * iterator)3326 void SerializerForBackgroundCompilation::VisitLdaNamedProperty(
3327     BytecodeArrayIterator* iterator) {
3328   Hints* receiver = &register_hints(iterator->GetRegisterOperand(0));
3329   NameRef name(broker(),
3330                iterator->GetConstantForIndexOperand(1, broker()->isolate()));
3331   FeedbackSlot slot = iterator->GetSlotOperand(2);
3332   ProcessNamedPropertyAccess(receiver, name, slot, AccessMode::kLoad);
3333 }
3334 
VisitLdaNamedPropertyFromSuper(BytecodeArrayIterator * iterator)3335 void SerializerForBackgroundCompilation::VisitLdaNamedPropertyFromSuper(
3336     BytecodeArrayIterator* iterator) {
3337   Hints* receiver = &register_hints(iterator->GetRegisterOperand(0));
3338   NameRef name(broker(),
3339                iterator->GetConstantForIndexOperand(1, broker()->isolate()));
3340   FeedbackSlot slot = iterator->GetSlotOperand(2);
3341   ProcessNamedSuperPropertyAccess(receiver, name, slot, AccessMode::kLoad);
3342 }
3343 
3344 // TODO(neis): Do feedback-independent serialization also for *NoFeedback
3345 // bytecodes.
VisitLdaNamedPropertyNoFeedback(BytecodeArrayIterator * iterator)3346 void SerializerForBackgroundCompilation::VisitLdaNamedPropertyNoFeedback(
3347     BytecodeArrayIterator* iterator) {
3348   NameRef(broker(),
3349           iterator->GetConstantForIndexOperand(1, broker()->isolate()));
3350 }
3351 
VisitStaNamedProperty(BytecodeArrayIterator * iterator)3352 void SerializerForBackgroundCompilation::VisitStaNamedProperty(
3353     BytecodeArrayIterator* iterator) {
3354   Hints* receiver = &register_hints(iterator->GetRegisterOperand(0));
3355   NameRef name(broker(),
3356                iterator->GetConstantForIndexOperand(1, broker()->isolate()));
3357   FeedbackSlot slot = iterator->GetSlotOperand(2);
3358   ProcessNamedPropertyAccess(receiver, name, slot, AccessMode::kStore);
3359 }
3360 
VisitStaNamedPropertyNoFeedback(BytecodeArrayIterator * iterator)3361 void SerializerForBackgroundCompilation::VisitStaNamedPropertyNoFeedback(
3362     BytecodeArrayIterator* iterator) {
3363   NameRef(broker(),
3364           iterator->GetConstantForIndexOperand(1, broker()->isolate()));
3365 }
3366 
VisitStaNamedOwnProperty(BytecodeArrayIterator * iterator)3367 void SerializerForBackgroundCompilation::VisitStaNamedOwnProperty(
3368     BytecodeArrayIterator* iterator) {
3369   Hints* receiver = &register_hints(iterator->GetRegisterOperand(0));
3370   NameRef name(broker(),
3371                iterator->GetConstantForIndexOperand(1, broker()->isolate()));
3372   FeedbackSlot slot = iterator->GetSlotOperand(2);
3373   ProcessNamedPropertyAccess(receiver, name, slot, AccessMode::kStoreInLiteral);
3374 }
3375 
VisitTestIn(BytecodeArrayIterator * iterator)3376 void SerializerForBackgroundCompilation::VisitTestIn(
3377     BytecodeArrayIterator* iterator) {
3378   Hints* receiver = &environment()->accumulator_hints();
3379   Hints const& key = register_hints(iterator->GetRegisterOperand(0));
3380   FeedbackSlot slot = iterator->GetSlotOperand(1);
3381   ProcessKeyedPropertyAccess(receiver, key, slot, AccessMode::kHas, false);
3382 }
3383 
3384 // For JSNativeContextSpecialization::ReduceJSOrdinaryHasInstance.
ProcessConstantForOrdinaryHasInstance(HeapObjectRef const & constructor,bool * walk_prototypes)3385 void SerializerForBackgroundCompilation::ProcessConstantForOrdinaryHasInstance(
3386     HeapObjectRef const& constructor, bool* walk_prototypes) {
3387   if (constructor.IsJSBoundFunction()) {
3388     constructor.AsJSBoundFunction().Serialize();
3389     ProcessConstantForInstanceOf(
3390         constructor.AsJSBoundFunction().bound_target_function(),
3391         walk_prototypes);
3392   } else if (constructor.IsJSFunction()) {
3393     constructor.AsJSFunction().Serialize();
3394     *walk_prototypes =
3395         *walk_prototypes ||
3396         (constructor.map().has_prototype_slot() &&
3397          constructor.AsJSFunction().has_prototype() &&
3398          !constructor.AsJSFunction().PrototypeRequiresRuntimeLookup());
3399   }
3400 }
3401 
ProcessConstantForInstanceOf(ObjectRef const & constructor,bool * walk_prototypes)3402 void SerializerForBackgroundCompilation::ProcessConstantForInstanceOf(
3403     ObjectRef const& constructor, bool* walk_prototypes) {
3404   if (!constructor.IsHeapObject()) return;
3405   HeapObjectRef constructor_heap_object = constructor.AsHeapObject();
3406 
3407   PropertyAccessInfo access_info = broker()->GetPropertyAccessInfo(
3408       constructor_heap_object.map(),
3409       NameRef(broker(), broker()->isolate()->factory()->has_instance_symbol()),
3410       AccessMode::kLoad, dependencies(),
3411       SerializationPolicy::kSerializeIfNeeded);
3412 
3413   if (access_info.IsNotFound()) {
3414     ProcessConstantForOrdinaryHasInstance(constructor_heap_object,
3415                                           walk_prototypes);
3416   } else if (access_info.IsDataConstant()) {
3417     Handle<JSObject> holder;
3418     bool found_on_proto = access_info.holder().ToHandle(&holder);
3419     JSObjectRef holder_ref = found_on_proto ? JSObjectRef(broker(), holder)
3420                                             : constructor.AsJSObject();
3421     base::Optional<ObjectRef> constant = holder_ref.GetOwnDataProperty(
3422         access_info.field_representation(), access_info.field_index(),
3423         SerializationPolicy::kSerializeIfNeeded);
3424     CHECK(constant.has_value());
3425     if (constant->IsJSFunction()) {
3426       JSFunctionRef function = constant->AsJSFunction();
3427       function.Serialize();
3428       if (function.shared().HasBuiltinId() &&
3429           function.shared().builtin_id() ==
3430               Builtins::kFunctionPrototypeHasInstance) {
3431         // For JSCallReducer::ReduceFunctionPrototypeHasInstance.
3432         ProcessConstantForOrdinaryHasInstance(constructor_heap_object,
3433                                               walk_prototypes);
3434       }
3435     }
3436   }
3437 }
3438 
VisitTestInstanceOf(BytecodeArrayIterator * iterator)3439 void SerializerForBackgroundCompilation::VisitTestInstanceOf(
3440     BytecodeArrayIterator* iterator) {
3441   Hints const& lhs = register_hints(iterator->GetRegisterOperand(0));
3442   Hints rhs = environment()->accumulator_hints();
3443   FeedbackSlot slot = iterator->GetSlotOperand(1);
3444 
3445   if (slot.IsInvalid() || feedback_vector().is_null()) return;
3446   FeedbackSource source(feedback_vector(), slot);
3447   ProcessedFeedback const& feedback =
3448       broker()->ProcessFeedbackForInstanceOf(source);
3449 
3450   // Incorporate feedback (about rhs) into hints copy to simplify processing.
3451   // TODO(neis): Propagate into original hints?
3452   if (!feedback.IsInsufficient()) {
3453     InstanceOfFeedback const& rhs_feedback = feedback.AsInstanceOf();
3454     if (rhs_feedback.value().has_value()) {
3455       rhs = rhs.Copy(zone());
3456       Handle<JSObject> constructor = rhs_feedback.value()->object();
3457       rhs.AddConstant(constructor, zone(), broker());
3458     }
3459   }
3460 
3461   bool walk_prototypes = false;
3462   for (Handle<Object> constant : rhs.constants()) {
3463     ProcessConstantForInstanceOf(ObjectRef(broker(), constant),
3464                                  &walk_prototypes);
3465   }
3466   if (walk_prototypes) ProcessHintsForHasInPrototypeChain(lhs);
3467 
3468   environment()->accumulator_hints() = Hints();
3469 }
3470 
VisitToNumeric(BytecodeArrayIterator * iterator)3471 void SerializerForBackgroundCompilation::VisitToNumeric(
3472     BytecodeArrayIterator* iterator) {
3473   FeedbackSlot slot = iterator->GetSlotOperand(0);
3474   ProcessUnaryOrBinaryOperation(slot, false);
3475 }
3476 
VisitToNumber(BytecodeArrayIterator * iterator)3477 void SerializerForBackgroundCompilation::VisitToNumber(
3478     BytecodeArrayIterator* iterator) {
3479   FeedbackSlot slot = iterator->GetSlotOperand(0);
3480   ProcessUnaryOrBinaryOperation(slot, false);
3481 }
3482 
VisitThrowReferenceErrorIfHole(BytecodeArrayIterator * iterator)3483 void SerializerForBackgroundCompilation::VisitThrowReferenceErrorIfHole(
3484     BytecodeArrayIterator* iterator) {
3485   ObjectRef(broker(),
3486             iterator->GetConstantForIndexOperand(0, broker()->isolate()));
3487 }
3488 
VisitStaKeyedProperty(BytecodeArrayIterator * iterator)3489 void SerializerForBackgroundCompilation::VisitStaKeyedProperty(
3490     BytecodeArrayIterator* iterator) {
3491   Hints* receiver = &register_hints(iterator->GetRegisterOperand(0));
3492   Hints const& key = register_hints(iterator->GetRegisterOperand(1));
3493   FeedbackSlot slot = iterator->GetSlotOperand(2);
3494   ProcessKeyedPropertyAccess(receiver, key, slot, AccessMode::kStore, true);
3495 }
3496 
VisitStaInArrayLiteral(BytecodeArrayIterator * iterator)3497 void SerializerForBackgroundCompilation::VisitStaInArrayLiteral(
3498     BytecodeArrayIterator* iterator) {
3499   Hints* receiver = &register_hints(iterator->GetRegisterOperand(0));
3500   Hints const& key = register_hints(iterator->GetRegisterOperand(1));
3501   FeedbackSlot slot = iterator->GetSlotOperand(2);
3502   ProcessKeyedPropertyAccess(receiver, key, slot, AccessMode::kStoreInLiteral,
3503                              true);
3504 }
3505 
VisitStaDataPropertyInLiteral(BytecodeArrayIterator * iterator)3506 void SerializerForBackgroundCompilation::VisitStaDataPropertyInLiteral(
3507     BytecodeArrayIterator* iterator) {
3508   Hints* receiver = &register_hints(iterator->GetRegisterOperand(0));
3509   Hints const& key = register_hints(iterator->GetRegisterOperand(1));
3510   FeedbackSlot slot = iterator->GetSlotOperand(3);
3511   ProcessKeyedPropertyAccess(receiver, key, slot, AccessMode::kStoreInLiteral,
3512                              false);
3513 }
3514 
3515 #define DEFINE_CLEAR_ACCUMULATOR(name, ...)             \
3516   void SerializerForBackgroundCompilation::Visit##name( \
3517       BytecodeArrayIterator* iterator) {                \
3518     environment()->accumulator_hints() = Hints();       \
3519   }
3520 CLEAR_ACCUMULATOR_LIST(DEFINE_CLEAR_ACCUMULATOR)
3521 #undef DEFINE_CLEAR_ACCUMULATOR
3522 
3523 #define DEFINE_CONDITIONAL_JUMP(name, ...)              \
3524   void SerializerForBackgroundCompilation::Visit##name( \
3525       BytecodeArrayIterator* iterator) {                \
3526     ProcessJump(iterator);                              \
3527   }
3528 CONDITIONAL_JUMPS_LIST(DEFINE_CONDITIONAL_JUMP)
3529 #undef DEFINE_CONDITIONAL_JUMP
3530 
3531 #define DEFINE_UNCONDITIONAL_JUMP(name, ...)            \
3532   void SerializerForBackgroundCompilation::Visit##name( \
3533       BytecodeArrayIterator* iterator) {                \
3534     ProcessJump(iterator);                              \
3535     environment()->Kill();                              \
3536   }
3537 UNCONDITIONAL_JUMPS_LIST(DEFINE_UNCONDITIONAL_JUMP)
3538 #undef DEFINE_UNCONDITIONAL_JUMP
3539 
3540 #define DEFINE_IGNORE(name, ...)                        \
3541   void SerializerForBackgroundCompilation::Visit##name( \
3542       BytecodeArrayIterator* iterator) {}
3543 IGNORED_BYTECODE_LIST(DEFINE_IGNORE)
3544 #undef DEFINE_IGNORE
3545 
3546 #define DEFINE_UNREACHABLE(name, ...)                   \
3547   void SerializerForBackgroundCompilation::Visit##name( \
3548       BytecodeArrayIterator* iterator) {                \
3549     UNREACHABLE();                                      \
3550   }
3551 UNREACHABLE_BYTECODE_LIST(DEFINE_UNREACHABLE)
3552 #undef DEFINE_UNREACHABLE
3553 
3554 #define DEFINE_KILL(name, ...)                          \
3555   void SerializerForBackgroundCompilation::Visit##name( \
3556       BytecodeArrayIterator* iterator) {                \
3557     environment()->Kill();                              \
3558   }
3559 KILL_ENVIRONMENT_LIST(DEFINE_KILL)
3560 #undef DEFINE_KILL
3561 
3562 #define DEFINE_BINARY_OP(name, ...)                     \
3563   void SerializerForBackgroundCompilation::Visit##name( \
3564       BytecodeArrayIterator* iterator) {                \
3565     FeedbackSlot slot = iterator->GetSlotOperand(1);    \
3566     ProcessUnaryOrBinaryOperation(slot, true);          \
3567   }
3568 BINARY_OP_LIST(DEFINE_BINARY_OP)
3569 #undef DEFINE_BINARY_OP
3570 
3571 #define DEFINE_COMPARE_OP(name, ...)                    \
3572   void SerializerForBackgroundCompilation::Visit##name( \
3573       BytecodeArrayIterator* iterator) {                \
3574     FeedbackSlot slot = iterator->GetSlotOperand(1);    \
3575     ProcessCompareOperation(slot);                      \
3576   }
3577 COMPARE_OP_LIST(DEFINE_COMPARE_OP)
3578 #undef DEFINE_COMPARE_OP
3579 
3580 #define DEFINE_UNARY_OP(name, ...)                      \
3581   void SerializerForBackgroundCompilation::Visit##name( \
3582       BytecodeArrayIterator* iterator) {                \
3583     FeedbackSlot slot = iterator->GetSlotOperand(0);    \
3584     ProcessUnaryOrBinaryOperation(slot, true);          \
3585   }
3586 UNARY_OP_LIST(DEFINE_UNARY_OP)
3587 #undef DEFINE_UNARY_OP
3588 
3589 #undef BINARY_OP_LIST
3590 #undef CLEAR_ACCUMULATOR_LIST
3591 #undef COMPARE_OP_LIST
3592 #undef CONDITIONAL_JUMPS_LIST
3593 #undef IGNORED_BYTECODE_LIST
3594 #undef KILL_ENVIRONMENT_LIST
3595 #undef SUPPORTED_BYTECODE_LIST
3596 #undef UNARY_OP_LIST
3597 #undef UNCONDITIONAL_JUMPS_LIST
3598 #undef UNREACHABLE_BYTECODE_LIST
3599 
3600 }  // namespace compiler
3601 }  // namespace internal
3602 }  // namespace v8
3603