serializer-for-background-compilation.cc 134 KB
Newer Older
1 2 3 4 5 6
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/compiler/serializer-for-background-compilation.h"

7 8
#include <sstream>

9 10
#include "src/base/optional.h"
#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 19
#include "src/interpreter/bytecode-array-iterator.h"
#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 26 27 28 29 30
#include "src/zone/zone.h"

namespace v8 {
namespace internal {
namespace compiler {

31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
#define KILL_ENVIRONMENT_LIST(V) \
  V(Abort)                       \
  V(ReThrow)                     \
  V(Throw)

#define CLEAR_ACCUMULATOR_LIST(V) \
  V(CallRuntime)                  \
  V(CloneObject)                  \
  V(CreateArrayFromIterable)      \
  V(CreateEmptyObjectLiteral)     \
  V(CreateMappedArguments)        \
  V(CreateRestParameter)          \
  V(CreateUnmappedArguments)      \
  V(DeletePropertySloppy)         \
  V(DeletePropertyStrict)         \
  V(ForInContinue)                \
  V(ForInEnumerate)               \
  V(ForInStep)                    \
  V(LogicalNot)                   \
  V(SetPendingMessage)            \
  V(TestNull)                     \
  V(TestReferenceEqual)           \
  V(TestTypeOf)                   \
  V(TestUndefined)                \
  V(TestUndetectable)             \
  V(ToBooleanLogicalNot)          \
  V(ToName)                       \
  V(ToString)                     \
  V(TypeOf)

#define UNCONDITIONAL_JUMPS_LIST(V) \
  V(Jump)                           \
  V(JumpConstant)                   \
  V(JumpLoop)

#define CONDITIONAL_JUMPS_LIST(V) \
  V(JumpIfFalse)                  \
  V(JumpIfFalseConstant)          \
  V(JumpIfJSReceiver)             \
  V(JumpIfJSReceiverConstant)     \
  V(JumpIfNotNull)                \
  V(JumpIfNotNullConstant)        \
  V(JumpIfNotUndefined)           \
  V(JumpIfNotUndefinedConstant)   \
  V(JumpIfNull)                   \
  V(JumpIfNullConstant)           \
  V(JumpIfToBooleanFalse)         \
  V(JumpIfToBooleanFalseConstant) \
  V(JumpIfToBooleanTrue)          \
  V(JumpIfToBooleanTrueConstant)  \
  V(JumpIfTrue)                   \
  V(JumpIfTrueConstant)           \
  V(JumpIfUndefined)              \
84 85 86
  V(JumpIfUndefinedConstant)      \
  V(JumpIfUndefinedOrNull)        \
  V(JumpIfUndefinedOrNullConstant)
87 88 89 90 91 92 93 94 95 96 97

#define IGNORED_BYTECODE_LIST(V)      \
  V(IncBlockCounter)                  \
  V(ThrowSuperAlreadyCalledIfNotHole) \
  V(ThrowSuperNotCalledIfHole)

#define UNREACHABLE_BYTECODE_LIST(V) \
  V(ExtraWide)                       \
  V(Illegal)                         \
  V(Wide)

98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
#define BINARY_OP_LIST(V) \
  V(Add)                  \
  V(AddSmi)               \
  V(BitwiseAnd)           \
  V(BitwiseAndSmi)        \
  V(BitwiseOr)            \
  V(BitwiseOrSmi)         \
  V(BitwiseXor)           \
  V(BitwiseXorSmi)        \
  V(Div)                  \
  V(DivSmi)               \
  V(Exp)                  \
  V(ExpSmi)               \
  V(Mod)                  \
  V(ModSmi)               \
  V(Mul)                  \
  V(MulSmi)               \
  V(ShiftLeft)            \
  V(ShiftLeftSmi)         \
  V(ShiftRight)           \
  V(ShiftRightSmi)        \
  V(ShiftRightLogical)    \
  V(ShiftRightLogicalSmi) \
  V(Sub)                  \
  V(SubSmi)

#define UNARY_OP_LIST(V) \
  V(BitwiseNot)          \
  V(Dec)                 \
  V(Inc)                 \
  V(Negate)

#define COMPARE_OP_LIST(V)  \
  V(TestEqual)              \
  V(TestEqualStrict)        \
  V(TestGreaterThan)        \
  V(TestGreaterThanOrEqual) \
  V(TestLessThan)           \
  V(TestLessThanOrEqual)

138 139 140
#define SUPPORTED_BYTECODE_LIST(V)    \
  V(CallAnyReceiver)                  \
  V(CallJSRuntime)                    \
141
  V(CallNoFeedback)                   \
142 143 144 145 146 147 148 149 150 151 152
  V(CallProperty)                     \
  V(CallProperty0)                    \
  V(CallProperty1)                    \
  V(CallProperty2)                    \
  V(CallUndefinedReceiver)            \
  V(CallUndefinedReceiver0)           \
  V(CallUndefinedReceiver1)           \
  V(CallUndefinedReceiver2)           \
  V(CallWithSpread)                   \
  V(Construct)                        \
  V(ConstructWithSpread)              \
153
  V(CreateArrayLiteral)               \
154 155 156
  V(CreateBlockContext)               \
  V(CreateCatchContext)               \
  V(CreateClosure)                    \
157
  V(CreateEmptyArrayLiteral)          \
158 159
  V(CreateEvalContext)                \
  V(CreateFunctionContext)            \
160 161
  V(CreateObjectLiteral)              \
  V(CreateRegExpLiteral)              \
162
  V(CreateWithContext)                \
163 164
  V(ForInNext)                        \
  V(ForInPrepare)                     \
165
  V(GetIterator)                      \
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
  V(GetSuperConstructor)              \
  V(GetTemplateObject)                \
  V(InvokeIntrinsic)                  \
  V(LdaConstant)                      \
  V(LdaContextSlot)                   \
  V(LdaCurrentContextSlot)            \
  V(LdaImmutableContextSlot)          \
  V(LdaImmutableCurrentContextSlot)   \
  V(LdaModuleVariable)                \
  V(LdaFalse)                         \
  V(LdaGlobal)                        \
  V(LdaGlobalInsideTypeof)            \
  V(LdaKeyedProperty)                 \
  V(LdaLookupContextSlot)             \
  V(LdaLookupContextSlotInsideTypeof) \
  V(LdaLookupGlobalSlot)              \
  V(LdaLookupGlobalSlotInsideTypeof)  \
183 184
  V(LdaLookupSlot)                    \
  V(LdaLookupSlotInsideTypeof)        \
185
  V(LdaNamedProperty)                 \
186
  V(LdaNamedPropertyNoFeedback)       \
187 188 189 190 191 192 193 194 195 196 197 198 199
  V(LdaNull)                          \
  V(Ldar)                             \
  V(LdaSmi)                           \
  V(LdaTheHole)                       \
  V(LdaTrue)                          \
  V(LdaUndefined)                     \
  V(LdaZero)                          \
  V(Mov)                              \
  V(PopContext)                       \
  V(PushContext)                      \
  V(Return)                           \
  V(StaContextSlot)                   \
  V(StaCurrentContextSlot)            \
200
  V(StaDataPropertyInLiteral)         \
201 202 203
  V(StaGlobal)                        \
  V(StaInArrayLiteral)                \
  V(StaKeyedProperty)                 \
204
  V(StaLookupSlot)                    \
205 206 207
  V(StaModuleVariable)                \
  V(StaNamedOwnProperty)              \
  V(StaNamedProperty)                 \
208
  V(StaNamedPropertyNoFeedback)       \
209 210 211 212
  V(Star)                             \
  V(SwitchOnGeneratorState)           \
  V(SwitchOnSmiNoFeedback)            \
  V(TestIn)                           \
213
  V(TestInstanceOf)                   \
214
  V(ThrowReferenceErrorIfHole)        \
215 216 217 218
  V(ToNumber)                         \
  V(ToNumeric)                        \
  BINARY_OP_LIST(V)                   \
  COMPARE_OP_LIST(V)                  \
219 220 221 222
  CLEAR_ACCUMULATOR_LIST(V)           \
  CONDITIONAL_JUMPS_LIST(V)           \
  IGNORED_BYTECODE_LIST(V)            \
  KILL_ENVIRONMENT_LIST(V)            \
223
  UNARY_OP_LIST(V)                    \
224 225 226
  UNCONDITIONAL_JUMPS_LIST(V)         \
  UNREACHABLE_BYTECODE_LIST(V)

227 228 229 230 231
struct HintsImpl : public ZoneObject {
  explicit HintsImpl(Zone* zone) : zone_(zone) {}

  ConstantsSet constants_;
  MapsSet maps_;
232 233 234
  VirtualClosuresSet virtual_closures_;
  VirtualContextsSet virtual_contexts_;
  VirtualBoundFunctionsSet virtual_bound_functions_;
235 236 237 238 239 240 241 242 243 244

  Zone* const zone_;
};

void Hints::EnsureAllocated(Zone* zone, bool check_zone_equality) {
  if (IsAllocated()) {
    if (check_zone_equality) CHECK_EQ(zone, impl_->zone_);
    // ... else {zone} lives no longer than {impl_->zone_} but we have no way of
    // checking that.
  } else {
245
    impl_ = zone->New<HintsImpl>(zone);
246 247 248
  }
  DCHECK(IsAllocated());
}
249

250
struct VirtualBoundFunction {
251 252
  Hints const bound_target;
  HintsVector const bound_arguments;
253

254
  VirtualBoundFunction(Hints const& target, const HintsVector& arguments)
255 256 257 258 259 260 261 262 263 264 265 266 267
      : bound_target(target), bound_arguments(arguments) {}

  bool operator==(const VirtualBoundFunction& other) const {
    if (bound_arguments.size() != other.bound_arguments.size()) return false;
    if (bound_target != other.bound_target) return false;

    for (size_t i = 0; i < bound_arguments.size(); ++i) {
      if (bound_arguments[i] != other.bound_arguments[i]) return false;
    }
    return true;
  }
};

268
// A VirtualClosure is a SharedFunctionInfo and a FeedbackVector, plus
269
// Hints about the context in which a closure will be created from them.
270
class VirtualClosure {
271
 public:
272
  VirtualClosure(Handle<JSFunction> function, Isolate* isolate, Zone* zone);
273

274 275 276
  VirtualClosure(Handle<SharedFunctionInfo> shared,
                 Handle<FeedbackVector> feedback_vector,
                 Hints const& context_hints);
277 278 279

  Handle<SharedFunctionInfo> shared() const { return shared_; }
  Handle<FeedbackVector> feedback_vector() const { return feedback_vector_; }
280
  Hints const& context_hints() const { return context_hints_; }
281

282
  bool operator==(const VirtualClosure& other) const {
283
    // A feedback vector is never used for more than one SFI.  There might,
284 285 286
    // however, be two virtual closures with the same SFI and vector, but
    // different context hints. crbug.com/1024282 has a link to a document
    // describing why the context_hints_ might be different in that case.
287 288
    DCHECK_IMPLIES(feedback_vector_.equals(other.feedback_vector_),
                   shared_.equals(other.shared_));
289 290
    return feedback_vector_.equals(other.feedback_vector_) &&
           context_hints_ == other.context_hints_;
291 292 293
  }

 private:
294 295 296
  Handle<SharedFunctionInfo> const shared_;
  Handle<FeedbackVector> const feedback_vector_;
  Hints const context_hints_;
297 298
};

299 300
// A CompilationSubject is a VirtualClosure, optionally with a matching
// concrete closure.
301 302
class CompilationSubject {
 public:
303
  explicit CompilationSubject(VirtualClosure virtual_closure)
304
      : virtual_closure_(virtual_closure), closure_() {}
305

306
  // The zone parameter is to correctly initialize the virtual closure,
307
  // which contains zone-allocated context information.
308
  CompilationSubject(Handle<JSFunction> closure, Isolate* isolate, Zone* zone);
309

310
  const VirtualClosure& virtual_closure() const { return virtual_closure_; }
311 312 313
  MaybeHandle<JSFunction> closure() const { return closure_; }

 private:
314
  VirtualClosure const virtual_closure_;
315
  MaybeHandle<JSFunction> const closure_;
316 317
};

318
// A Callee is either a JSFunction (which may not have a feedback vector), or a
319 320
// VirtualClosure. Note that this is different from CompilationSubject, which
// always has a VirtualClosure.
321 322
class Callee {
 public:
323
  explicit Callee(Handle<JSFunction> jsfunction)
324 325 326
      : jsfunction_(jsfunction), virtual_closure_() {}
  explicit Callee(VirtualClosure const& virtual_closure)
      : jsfunction_(), virtual_closure_(virtual_closure) {}
327 328

  Handle<SharedFunctionInfo> shared(Isolate* isolate) const {
329 330
    return virtual_closure_.has_value()
               ? virtual_closure_->shared()
331 332 333 334 335
               : handle(jsfunction_.ToHandleChecked()->shared(), isolate);
  }

  bool HasFeedbackVector() const {
    Handle<JSFunction> function;
336
    return virtual_closure_.has_value() ||
337 338 339
           jsfunction_.ToHandleChecked()->has_feedback_vector();
  }

340
  CompilationSubject ToCompilationSubject(Isolate* isolate, Zone* zone) const {
341
    CHECK(HasFeedbackVector());
342 343
    return virtual_closure_.has_value()
               ? CompilationSubject(*virtual_closure_)
344
               : CompilationSubject(jsfunction_.ToHandleChecked(), isolate,
345
                                    zone);
346 347 348 349
  }

 private:
  MaybeHandle<JSFunction> const jsfunction_;
350
  base::Optional<VirtualClosure> const virtual_closure_;
351 352
};

353 354 355 356 357 358 359
// If a list of arguments (hints) is shorter than the function's parameter
// count, this enum expresses what we know about the missing arguments.
enum MissingArgumentsPolicy {
  kMissingArgumentsAreUndefined,  // ... as in the JS undefined value
  kMissingArgumentsAreUnknown,
};

360 361 362 363 364 365
// The SerializerForBackgroundCompilation makes sure that the relevant function
// data such as bytecode, SharedFunctionInfo and FeedbackVector, used by later
// optimizations in the compiler, is copied to the heap broker.
class SerializerForBackgroundCompilation {
 public:
  SerializerForBackgroundCompilation(
366 367 368
      ZoneStats* zone_stats, JSHeapBroker* broker,
      CompilationDependencies* dependencies, Handle<JSFunction> closure,
      SerializerForBackgroundCompilationFlags flags, BailoutId osr_offset);
369 370
  Hints Run();  // NOTE: Returns empty for an
                // already-serialized function.
371 372 373 374 375

  class Environment;

 private:
  SerializerForBackgroundCompilation(
376 377 378
      ZoneStats* zone_stats, JSHeapBroker* broker,
      CompilationDependencies* dependencies, CompilationSubject function,
      base::Optional<Hints> new_target, const HintsVector& arguments,
379
      MissingArgumentsPolicy padding,
380
      SerializerForBackgroundCompilationFlags flags, int nesting_level);
381

382
  bool BailoutOnUninitialized(ProcessedFeedback const& feedback);
383 384 385 386 387 388 389 390

  void TraverseBytecode();

#define DECLARE_VISIT_BYTECODE(name, ...) \
  void Visit##name(interpreter::BytecodeArrayIterator* iterator);
  SUPPORTED_BYTECODE_LIST(DECLARE_VISIT_BYTECODE)
#undef DECLARE_VISIT_BYTECODE

391 392
  Hints& register_hints(interpreter::Register reg);

393 394 395 396 397 398 399 400 401
  // Return a vector containing the hints for the given register range (in
  // order). Also prepare these hints for feedback backpropagation by allocating
  // any that aren't yet allocated.
  HintsVector PrepareArgumentsHints(interpreter::Register first, size_t count);

  // Like above except that the hints have to be given directly.
  template <typename... MoreHints>
  HintsVector PrepareArgumentsHints(Hints* hints, MoreHints... more);

402 403 404 405
  void ProcessCalleeForCallOrConstruct(Callee const& callee,
                                       base::Optional<Hints> new_target,
                                       const HintsVector& arguments,
                                       SpeculationMode speculation_mode,
406 407
                                       MissingArgumentsPolicy padding,
                                       Hints* result_hints);
408 409
  void ProcessCalleeForCallOrConstruct(Handle<Object> callee,
                                       base::Optional<Hints> new_target,
410
                                       const HintsVector& arguments,
411
                                       SpeculationMode speculation_mode,
412 413
                                       MissingArgumentsPolicy padding,
                                       Hints* result_hints);
414
  void ProcessCallOrConstruct(Hints callee, base::Optional<Hints> new_target,
415
                              HintsVector* arguments, FeedbackSlot slot,
416
                              MissingArgumentsPolicy padding);
417
  void ProcessCallOrConstructRecursive(Hints const& callee,
418 419 420 421 422 423 424
                                       base::Optional<Hints> new_target,
                                       const HintsVector& arguments,
                                       SpeculationMode speculation_mode,
                                       MissingArgumentsPolicy padding,
                                       Hints* result_hints);
  void ProcessNewTargetForConstruct(Hints const& new_target,
                                    Hints* result_hints);
425 426 427 428
  void ProcessCallVarArgs(
      ConvertReceiverMode receiver_mode, Hints const& callee,
      interpreter::Register first_reg, int reg_count, FeedbackSlot slot,
      MissingArgumentsPolicy padding = kMissingArgumentsAreUndefined);
429 430
  void ProcessApiCall(Handle<SharedFunctionInfo> target,
                      const HintsVector& arguments);
431 432
  void ProcessReceiverMapForApiCall(FunctionTemplateInfoRef target,
                                    Handle<Map> receiver);
433
  void ProcessBuiltinCall(Handle<SharedFunctionInfo> target,
434
                          base::Optional<Hints> new_target,
435
                          const HintsVector& arguments,
436
                          SpeculationMode speculation_mode,
437
                          MissingArgumentsPolicy padding, Hints* result_hints);
438 439 440

  void ProcessJump(interpreter::BytecodeArrayIterator* iterator);

441
  void ProcessKeyedPropertyAccess(Hints* receiver, Hints const& key,
442 443
                                  FeedbackSlot slot, AccessMode access_mode,
                                  bool honor_bailout_on_uninitialized);
444
  void ProcessNamedPropertyAccess(Hints* receiver, NameRef const& name,
445
                                  FeedbackSlot slot, AccessMode access_mode);
446 447 448
  void ProcessNamedAccess(Hints* receiver, NamedAccessFeedback const& feedback,
                          AccessMode access_mode, Hints* result_hints);
  void ProcessElementAccess(Hints const& receiver, Hints const& key,
449 450 451
                            ElementAccessFeedback const& feedback,
                            AccessMode access_mode);

452 453 454
  void ProcessModuleVariableAccess(
      interpreter::BytecodeArrayIterator* iterator);

455
  void ProcessHintsForObjectCreate(Hints const& prototype);
456 457
  void ProcessMapHintsForPromises(Hints const& receiver_hints);
  void ProcessHintsForPromiseResolve(Hints const& resolution_hints);
458
  void ProcessHintsForHasInPrototypeChain(Hints const& instance_hints);
459 460
  void ProcessHintsForRegExpTest(Hints const& regexp_hints);
  PropertyAccessInfo ProcessMapForRegExpTest(MapRef map);
461
  void ProcessHintsForFunctionBind(Hints const& receiver_hints);
462
  void ProcessHintsForObjectGetPrototype(Hints const& object_hints);
463 464 465 466 467 468
  void ProcessConstantForOrdinaryHasInstance(HeapObjectRef const& constructor,
                                             bool* walk_prototypes);
  void ProcessConstantForInstanceOf(ObjectRef const& constant,
                                    bool* walk_prototypes);
  void ProcessHintsForOrdinaryHasInstance(Hints const& constructor_hints,
                                          Hints const& instance_hints);
469

470 471 472 473 474 475 476
  void ProcessGlobalAccess(FeedbackSlot slot, bool is_load);

  void ProcessCompareOperation(FeedbackSlot slot);
  void ProcessForIn(FeedbackSlot slot);
  void ProcessUnaryOrBinaryOperation(FeedbackSlot slot,
                                     bool honor_bailout_on_uninitialized);

477
  PropertyAccessInfo ProcessMapForNamedPropertyAccess(
478 479 480
      Hints* receiver, MapRef receiver_map, NameRef const& name,
      AccessMode access_mode, base::Optional<JSObjectRef> concrete_receiver,
      Hints* result_hints);
481

482 483 484
  void ProcessCreateContext(interpreter::BytecodeArrayIterator* iterator,
                            int scopeinfo_operand_index);

485 486 487 488 489
  enum ContextProcessingMode {
    kIgnoreSlot,
    kSerializeSlot,
  };

490 491
  void ProcessContextAccess(Hints const& context_hints, int slot, int depth,
                            ContextProcessingMode mode,
492
                            Hints* result_hints = nullptr);
493
  void ProcessImmutableLoad(ContextRef const& context, int slot,
494 495
                            ContextProcessingMode mode,
                            Hints* new_accumulator_hints);
496 497 498 499 500 501 502 503 504 505
  void ProcessLdaLookupGlobalSlot(interpreter::BytecodeArrayIterator* iterator);
  void ProcessLdaLookupContextSlot(
      interpreter::BytecodeArrayIterator* iterator);

  // Performs extension lookups for [0, depth) like
  // BytecodeGraphBuilder::CheckContextExtensions().
  void ProcessCheckContextExtensions(int depth);

  Hints RunChildSerializer(CompilationSubject function,
                           base::Optional<Hints> new_target,
506 507
                           const HintsVector& arguments,
                           MissingArgumentsPolicy padding);
508 509 510 511 512 513 514 515 516 517 518

  // When (forward-)branching bytecodes are encountered, e.g. a conditional
  // jump, we call ContributeToJumpTargetEnvironment to "remember" the current
  // environment, associated with the jump target offset. When serialization
  // eventually reaches that offset, we call IncorporateJumpTargetEnvironment to
  // merge that environment back into whatever is the current environment then.
  // Note: Since there may be multiple jumps to the same target,
  // ContributeToJumpTargetEnvironment may actually do a merge as well.
  void ContributeToJumpTargetEnvironment(int target_offset);
  void IncorporateJumpTargetEnvironment(int target_offset);

519 520
  VirtualClosure function() const { return function_; }

521 522
  Hints& return_value_hints() { return return_value_hints_; }

523
  Handle<FeedbackVector> feedback_vector() const;
524
  Handle<BytecodeArray> bytecode_array() const;
525 526
  BytecodeAnalysis const& GetBytecodeAnalysis(
      SerializationPolicy policy = SerializationPolicy::kAssumeSerialized);
527 528 529

  JSHeapBroker* broker() const { return broker_; }
  CompilationDependencies* dependencies() const { return dependencies_; }
530
  Zone* zone() { return zone_scope_.zone(); }
531 532 533 534 535 536
  Environment* environment() const { return environment_; }
  SerializerForBackgroundCompilationFlags flags() const { return flags_; }
  BailoutId osr_offset() const { return osr_offset_; }

  JSHeapBroker* const broker_;
  CompilationDependencies* const dependencies_;
537
  ZoneStats::Scope zone_scope_;
538
  SerializerForBackgroundCompilationFlags const flags_;
539 540 541
  // Instead of storing the virtual_closure here, we could extract it from the
  // {closure_hints_} but that would be cumbersome.
  VirtualClosure const function_;
542
  BailoutId const osr_offset_;
543 544
  ZoneUnorderedMap<int, Environment*> jump_target_environments_;
  Environment* const environment_;
545
  HintsVector const arguments_;
546
  Hints return_value_hints_;
547
  Hints closure_hints_;
548 549

  int nesting_level_ = 0;
550 551 552
};

void RunSerializerForBackgroundCompilation(
553 554 555 556 557
    ZoneStats* zone_stats, JSHeapBroker* broker,
    CompilationDependencies* dependencies, Handle<JSFunction> closure,
    SerializerForBackgroundCompilationFlags flags, BailoutId osr_offset) {
  SerializerForBackgroundCompilation serializer(
      zone_stats, broker, dependencies, closure, flags, osr_offset);
558 559 560
  serializer.Run();
}

561 562
using BytecodeArrayIterator = interpreter::BytecodeArrayIterator;

563 564 565
VirtualClosure::VirtualClosure(Handle<SharedFunctionInfo> shared,
                               Handle<FeedbackVector> feedback_vector,
                               Hints const& context_hints)
566 567
    : shared_(shared),
      feedback_vector_(feedback_vector),
568 569
      context_hints_(context_hints) {
  // The checked invariant rules out recursion and thus avoids complexity.
570
  CHECK(context_hints_.virtual_closures().IsEmpty());
571
}
572

573
VirtualClosure::VirtualClosure(Handle<JSFunction> function, Isolate* isolate,
574
                               Zone* zone)
575
    : shared_(handle(function->shared(), isolate)),
576
      feedback_vector_(function->feedback_vector(), isolate),
577 578
      context_hints_(
          Hints::SingleConstant(handle(function->context(), isolate), zone)) {
579
  // The checked invariant rules out recursion and thus avoids complexity.
580
  CHECK(context_hints_.virtual_closures().IsEmpty());
581 582
}

583
CompilationSubject::CompilationSubject(Handle<JSFunction> closure,
584 585
                                       Isolate* isolate, Zone* zone)
    : virtual_closure_(closure, isolate, zone), closure_(closure) {
586 587
  CHECK(closure->has_feedback_vector());
}
588

589 590 591 592 593 594 595
Hints Hints::Copy(Zone* zone) const {
  if (!IsAllocated()) return *this;
  Hints result;
  result.EnsureAllocated(zone);
  result.impl_->constants_ = impl_->constants_;
  result.impl_->maps_ = impl_->maps_;
  result.impl_->virtual_contexts_ = impl_->virtual_contexts_;
596
  result.impl_->virtual_closures_ = impl_->virtual_closures_;
597 598 599 600
  result.impl_->virtual_bound_functions_ = impl_->virtual_bound_functions_;
  return result;
}

601
bool Hints::operator==(Hints const& other) const {
602 603 604 605
  if (impl_ == other.impl_) return true;
  if (IsEmpty() && other.IsEmpty()) return true;
  return IsAllocated() && other.IsAllocated() &&
         constants() == other.constants() &&
606
         virtual_closures() == other.virtual_closures() &&
607 608 609 610 611
         maps() == other.maps() &&
         virtual_contexts() == other.virtual_contexts() &&
         virtual_bound_functions() == other.virtual_bound_functions();
}

612 613
bool Hints::operator!=(Hints const& other) const { return !(*this == other); }

614 615
#ifdef ENABLE_SLOW_DCHECKS
bool Hints::Includes(Hints const& other) const {
616 617
  if (impl_ == other.impl_ || other.IsEmpty()) return true;
  return IsAllocated() && constants().Includes(other.constants()) &&
618
         virtual_closures().Includes(other.virtual_closures()) &&
619
         maps().Includes(other.maps());
620 621 622
}
#endif

623
Hints Hints::SingleConstant(Handle<Object> constant, Zone* zone) {
624
  Hints result;
625
  result.AddConstant(constant, zone, nullptr);
626 627 628
  return result;
}

629
Hints Hints::SingleMap(Handle<Map> map, Zone* zone) {
630
  Hints result;
631
  result.AddMap(map, zone, nullptr);
632 633 634
  return result;
}

635 636 637
ConstantsSet Hints::constants() const {
  return IsAllocated() ? impl_->constants_ : ConstantsSet();
}
638

639
MapsSet Hints::maps() const { return IsAllocated() ? impl_->maps_ : MapsSet(); }
640

641 642
VirtualClosuresSet Hints::virtual_closures() const {
  return IsAllocated() ? impl_->virtual_closures_ : VirtualClosuresSet();
643 644
}

645 646
VirtualContextsSet Hints::virtual_contexts() const {
  return IsAllocated() ? impl_->virtual_contexts_ : VirtualContextsSet();
647 648
}

649 650 651
VirtualBoundFunctionsSet Hints::virtual_bound_functions() const {
  return IsAllocated() ? impl_->virtual_bound_functions_
                       : VirtualBoundFunctionsSet();
652 653
}

654 655
void Hints::AddVirtualContext(VirtualContext const& virtual_context, Zone* zone,
                              JSHeapBroker* broker) {
656
  EnsureAllocated(zone);
657 658 659 660 661
  if (impl_->virtual_contexts_.Size() >= kMaxHintsSize) {
    TRACE_BROKER_MISSING(broker,
                         "opportunity - limit for virtual contexts reached.");
    return;
  }
662
  impl_->virtual_contexts_.Add(virtual_context, impl_->zone_);
663 664
}

665 666
void Hints::AddConstant(Handle<Object> constant, Zone* zone,
                        JSHeapBroker* broker) {
667
  EnsureAllocated(zone);
668 669 670 671
  if (impl_->constants_.Size() >= kMaxHintsSize) {
    TRACE_BROKER_MISSING(broker, "opportunity - limit for constants reached.");
    return;
  }
672
  impl_->constants_.Add(constant, impl_->zone_);
673 674
}

675 676
void Hints::AddMap(Handle<Map> map, Zone* zone, JSHeapBroker* broker,
                   bool check_zone_equality) {
677
  EnsureAllocated(zone, check_zone_equality);
678 679 680 681
  if (impl_->maps_.Size() >= kMaxHintsSize) {
    TRACE_BROKER_MISSING(broker, "opportunity - limit for maps reached.");
    return;
  }
682 683
  impl_->maps_.Add(map, impl_->zone_);
}
684

685 686
void Hints::AddVirtualClosure(VirtualClosure const& virtual_closure, Zone* zone,
                              JSHeapBroker* broker) {
687
  EnsureAllocated(zone);
688 689 690 691 692
  if (impl_->virtual_closures_.Size() >= kMaxHintsSize) {
    TRACE_BROKER_MISSING(broker,
                         "opportunity - limit for virtual closures reached.");
    return;
  }
693
  impl_->virtual_closures_.Add(virtual_closure, impl_->zone_);
694 695
}

696
void Hints::AddVirtualBoundFunction(VirtualBoundFunction const& bound_function,
697
                                    Zone* zone, JSHeapBroker* broker) {
698
  EnsureAllocated(zone);
699 700 701 702 703
  if (impl_->virtual_bound_functions_.Size() >= kMaxHintsSize) {
    TRACE_BROKER_MISSING(
        broker, "opportunity - limit for virtual bound functions reached.");
    return;
  }
704 705 706
  // TODO(mslekova): Consider filtering the hints in the added bound function,
  // for example: a) Remove any non-JS(Bound)Function constants, b) Truncate the
  // argument vector the formal parameter count.
707
  impl_->virtual_bound_functions_.Add(bound_function, impl_->zone_);
708 709
}

710
void Hints::Add(Hints const& other, Zone* zone, JSHeapBroker* broker) {
711 712
  if (impl_ == other.impl_ || other.IsEmpty()) return;
  EnsureAllocated(zone);
713 714 715
  if (!Union(other)) {
    TRACE_BROKER_MISSING(broker, "opportunity - hints limit reached.");
  }
716 717
}

718
Hints Hints::CopyToParentZone(Zone* zone, JSHeapBroker* broker) const {
719 720 721 722
  if (!IsAllocated()) return *this;

  Hints result;

723 724 725 726
  for (auto const& x : constants()) result.AddConstant(x, zone, broker);
  for (auto const& x : maps()) result.AddMap(x, zone, broker);
  for (auto const& x : virtual_contexts())
    result.AddVirtualContext(x, zone, broker);
727 728

  // Adding hints from a child serializer run means copying data out from
729
  // a zone that's being destroyed. VirtualClosures and VirtualBoundFunction
730 731
  // have zone allocated data, so we've got to make a deep copy to eliminate
  // traces of the dying zone.
732 733 734
  for (auto const& x : virtual_closures()) {
    VirtualClosure new_virtual_closure(
        x.shared(), x.feedback_vector(),
735 736
        x.context_hints().CopyToParentZone(zone, broker));
    result.AddVirtualClosure(new_virtual_closure, zone, broker);
737
  }
738
  for (auto const& x : virtual_bound_functions()) {
739 740
    HintsVector new_arguments_hints(zone);
    for (auto hint : x.bound_arguments) {
741
      new_arguments_hints.push_back(hint.CopyToParentZone(zone, broker));
742
    }
743
    VirtualBoundFunction new_bound_function(
744 745
        x.bound_target.CopyToParentZone(zone, broker), new_arguments_hints);
    result.AddVirtualBoundFunction(new_bound_function, zone, broker);
746
  }
747 748

  return result;
749 750
}

751
bool Hints::IsEmpty() const {
752
  if (!IsAllocated()) return true;
753
  return constants().IsEmpty() && maps().IsEmpty() &&
754
         virtual_closures().IsEmpty() && virtual_contexts().IsEmpty() &&
755
         virtual_bound_functions().IsEmpty();
756 757
}

758 759 760 761 762 763 764 765 766
std::ostream& operator<<(std::ostream& out,
                         const VirtualContext& virtual_context) {
  out << "Distance " << virtual_context.distance << " from "
      << Brief(*virtual_context.context) << std::endl;
  return out;
}

std::ostream& operator<<(std::ostream& out, const Hints& hints);

767
std::ostream& operator<<(std::ostream& out,
768 769 770 771 772
                         const VirtualClosure& virtual_closure) {
  out << Brief(*virtual_closure.shared()) << std::endl;
  out << Brief(*virtual_closure.feedback_vector()) << std::endl;
  !virtual_closure.context_hints().IsEmpty() &&
      out << virtual_closure.context_hints() << "):" << std::endl;
773 774 775
  return out;
}

776 777 778 779 780 781 782 783 784 785
std::ostream& operator<<(std::ostream& out,
                         const VirtualBoundFunction& virtual_bound_function) {
  out << std::endl << "    Target: " << virtual_bound_function.bound_target;
  out << "    Arguments:" << std::endl;
  for (auto hint : virtual_bound_function.bound_arguments) {
    out << "    " << hint;
  }
  return out;
}

786
std::ostream& operator<<(std::ostream& out, const Hints& hints) {
787
  out << "(impl_ = " << hints.impl_ << ")\n";
788 789 790 791 792 793
  for (Handle<Object> constant : hints.constants()) {
    out << "  constant " << Brief(*constant) << std::endl;
  }
  for (Handle<Map> map : hints.maps()) {
    out << "  map " << Brief(*map) << std::endl;
  }
794 795
  for (VirtualClosure const& virtual_closure : hints.virtual_closures()) {
    out << "  virtual closure " << virtual_closure << std::endl;
796
  }
797 798 799
  for (VirtualContext const& virtual_context : hints.virtual_contexts()) {
    out << "  virtual context " << virtual_context << std::endl;
  }
800 801 802 803
  for (VirtualBoundFunction const& virtual_bound_function :
       hints.virtual_bound_functions()) {
    out << "  virtual bound function " << virtual_bound_function << std::endl;
  }
804 805 806
  return out;
}

807 808 809 810
void Hints::Reset(Hints* other, Zone* zone) {
  other->EnsureShareable(zone);
  *this = *other;
  DCHECK(IsAllocated());
811 812
}

813 814
class SerializerForBackgroundCompilation::Environment : public ZoneObject {
 public:
815
  Environment(Zone* zone, CompilationSubject function);
816
  Environment(Zone* zone, Isolate* isolate, CompilationSubject function,
817
              base::Optional<Hints> new_target, const HintsVector& arguments,
818
              MissingArgumentsPolicy padding);
819

820
  bool IsDead() const { return !alive_; }
821 822 823

  void Kill() {
    DCHECK(!IsDead());
824
    alive_ = false;
825 826 827
    DCHECK(IsDead());
  }

828 829 830 831 832 833
  void Resurrect() {
    DCHECK(IsDead());
    alive_ = true;
    DCHECK(!IsDead());
  }

834
  // Merge {other} into {this} environment (leaving {other} unmodified).
835
  void Merge(Environment* other, Zone* zone, JSHeapBroker* broker);
836

837
  Hints const& current_context_hints() const { return current_context_hints_; }
838
  Hints const& accumulator_hints() const { return accumulator_hints_; }
839

840 841 842
  Hints& current_context_hints() { return current_context_hints_; }
  Hints& accumulator_hints() { return accumulator_hints_; }
  Hints& register_hints(interpreter::Register reg);
843 844

 private:
845 846
  friend std::ostream& operator<<(std::ostream& out, const Environment& env);

847
  Hints current_context_hints_;
848
  Hints accumulator_hints_;
849

850 851 852 853
  HintsVector parameters_hints_;  // First parameter is the receiver.
  HintsVector locals_hints_;

  bool alive_ = true;
854 855 856
};

SerializerForBackgroundCompilation::Environment::Environment(
857
    Zone* zone, CompilationSubject function)
858 859 860 861 862 863 864 865 866 867
    : parameters_hints_(function.virtual_closure()
                            .shared()
                            ->GetBytecodeArray()
                            .parameter_count(),
                        Hints(), zone),
      locals_hints_(function.virtual_closure()
                        .shared()
                        ->GetBytecodeArray()
                        .register_count(),
                    Hints(), zone) {
868 869
  // Consume the virtual_closure's context hint information.
  current_context_hints_ = function.virtual_closure().context_hints();
870
}
871 872

SerializerForBackgroundCompilation::Environment::Environment(
873
    Zone* zone, Isolate* isolate, CompilationSubject function,
874
    base::Optional<Hints> new_target, const HintsVector& arguments,
875 876
    MissingArgumentsPolicy padding)
    : Environment(zone, function) {
877
  // Set the hints for the actually passed arguments, at most up to
878
  // the parameter_count.
879 880 881
  for (size_t i = 0; i < std::min(arguments.size(), parameters_hints_.size());
       ++i) {
    parameters_hints_[i] = arguments[i];
882 883
  }

884
  if (padding == kMissingArgumentsAreUndefined) {
885 886
    Hints const undefined_hint =
        Hints::SingleConstant(isolate->factory()->undefined_value(), zone);
887 888
    for (size_t i = arguments.size(); i < parameters_hints_.size(); ++i) {
      parameters_hints_[i] = undefined_hint;
889 890 891
    }
  } else {
    DCHECK_EQ(padding, kMissingArgumentsAreUnknown);
892
  }
893

894
  // Set hints for new_target.
895
  interpreter::Register new_target_reg =
896 897
      function.virtual_closure()
          .shared()
898
          ->GetBytecodeArray()
899
          .incoming_new_target_or_generator_register();
900
  if (new_target_reg.is_valid()) {
901 902 903
    Hints& hints = register_hints(new_target_reg);
    CHECK(hints.IsEmpty());
    if (new_target.has_value()) hints = *new_target;
904
  }
905 906
}

907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924
Hints& SerializerForBackgroundCompilation::register_hints(
    interpreter::Register reg) {
  if (reg.is_function_closure()) return closure_hints_;
  return environment()->register_hints(reg);
}

Hints& SerializerForBackgroundCompilation::Environment::register_hints(
    interpreter::Register reg) {
  if (reg.is_current_context()) return current_context_hints_;
  if (reg.is_parameter()) {
    return parameters_hints_[reg.ToParameterIndex(
        static_cast<int>(parameters_hints_.size()))];
  }
  DCHECK(!reg.is_function_closure());
  CHECK_LT(reg.index(), locals_hints_.size());
  return locals_hints_[reg.index()];
}

925 926
void SerializerForBackgroundCompilation::Environment::Merge(
    Environment* other, Zone* zone, JSHeapBroker* broker) {
927 928
  // {other} is guaranteed to have the same layout because it comes from an
  // earlier bytecode in the same function.
929 930
  DCHECK_EQ(parameters_hints_.size(), other->parameters_hints_.size());
  DCHECK_EQ(locals_hints_.size(), other->locals_hints_.size());
931

932
  if (IsDead()) {
933 934
    parameters_hints_ = other->parameters_hints_;
    locals_hints_ = other->locals_hints_;
935
    current_context_hints_ = other->current_context_hints_;
936 937
    accumulator_hints_ = other->accumulator_hints_;
    Resurrect();
938
  } else {
939
    for (size_t i = 0; i < parameters_hints_.size(); ++i) {
940
      parameters_hints_[i].Merge(other->parameters_hints_[i], zone, broker);
941 942
    }
    for (size_t i = 0; i < locals_hints_.size(); ++i) {
943
      locals_hints_[i].Merge(other->locals_hints_[i], zone, broker);
944
    }
945 946
    current_context_hints_.Merge(other->current_context_hints_, zone, broker);
    accumulator_hints_.Merge(other->accumulator_hints_, zone, broker);
947
  }
948

949 950 951
  CHECK(!IsDead());
}

952
bool Hints::Union(Hints const& other) {
953
  CHECK(IsAllocated());
954 955 956 957 958 959 960 961 962 963
  if (impl_->constants_.Size() + other.constants().Size() > kMaxHintsSize ||
      impl_->maps_.Size() + other.maps().Size() > kMaxHintsSize ||
      impl_->virtual_closures_.Size() + other.virtual_closures().Size() >
          kMaxHintsSize ||
      impl_->virtual_contexts_.Size() + other.virtual_contexts().Size() >
          kMaxHintsSize ||
      impl_->virtual_bound_functions_.Size() +
              other.virtual_bound_functions().Size() >
          kMaxHintsSize) {
    return false;
964
  }
965 966 967 968 969 970 971
  Zone* zone = impl_->zone_;
  impl_->constants_.Union(other.constants(), zone);
  impl_->maps_.Union(other.maps(), zone);
  impl_->virtual_closures_.Union(other.virtual_closures(), zone);
  impl_->virtual_contexts_.Union(other.virtual_contexts(), zone);
  impl_->virtual_bound_functions_.Union(other.virtual_bound_functions(), zone);
  return true;
972 973
}

974
void Hints::Merge(Hints const& other, Zone* zone, JSHeapBroker* broker) {
975 976 977 978 979 980 981 982 983
  if (impl_ == other.impl_) {
    return;
  }
  if (!IsAllocated()) {
    *this = other.Copy(zone);
    DCHECK(IsAllocated());
    return;
  }
  *this = this->Copy(zone);
984 985 986
  if (!Union(other)) {
    TRACE_BROKER_MISSING(broker, "opportunity - hints limit reached.");
  }
987
  DCHECK(IsAllocated());
988 989 990 991 992 993 994
}

std::ostream& operator<<(
    std::ostream& out,
    const SerializerForBackgroundCompilation::Environment& env) {
  std::ostringstream output_stream;

995 996 997 998
  if (env.IsDead()) {
    output_stream << "dead\n";
  } else {
    output_stream << "alive\n";
999 1000
    for (size_t i = 0; i < env.parameters_hints_.size(); ++i) {
      Hints const& hints = env.parameters_hints_[i];
1001
      if (!hints.IsEmpty()) {
1002 1003
        if (i == 0) {
          output_stream << "Hints for <this>: ";
1004
        } else {
1005
          output_stream << "Hints for a" << i - 1 << ": ";
1006 1007
        }
        output_stream << hints;
1008
      }
1009
    }
1010 1011 1012
    for (size_t i = 0; i < env.locals_hints_.size(); ++i) {
      Hints const& hints = env.locals_hints_[i];
      if (!hints.IsEmpty()) {
1013
        output_stream << "Hints for r" << i << ": " << hints;
1014 1015
      }
    }
1016
  }
1017

1018
  if (!env.current_context_hints().IsEmpty()) {
1019
    output_stream << "Hints for <context>: " << env.current_context_hints();
1020
  }
1021 1022 1023
  if (!env.accumulator_hints().IsEmpty()) {
    output_stream << "Hints for <accumulator>: " << env.accumulator_hints();
  }
1024 1025 1026 1027 1028

  out << output_stream.str();
  return out;
}

1029
SerializerForBackgroundCompilation::SerializerForBackgroundCompilation(
1030 1031 1032
    ZoneStats* zone_stats, JSHeapBroker* broker,
    CompilationDependencies* dependencies, Handle<JSFunction> closure,
    SerializerForBackgroundCompilationFlags flags, BailoutId osr_offset)
1033
    : broker_(broker),
1034
      dependencies_(dependencies),
1035
      zone_scope_(zone_stats, ZONE_NAME),
1036
      flags_(flags),
1037
      function_(closure, broker->isolate(), zone()),
1038
      osr_offset_(osr_offset),
1039
      jump_target_environments_(zone()),
1040
      environment_(zone()->New<Environment>(
1041
          zone(), CompilationSubject(closure, broker_->isolate(), zone()))),
1042
      arguments_(zone()) {
1043
  closure_hints_.AddConstant(closure, zone(), broker_);
1044
  JSFunctionRef(broker, closure).Serialize();
1045 1046 1047

  TRACE_BROKER(broker_, "Hints for <closure>: " << closure_hints_);
  TRACE_BROKER(broker_, "Initial environment:\n" << *environment_);
1048
}
1049

1050
SerializerForBackgroundCompilation::SerializerForBackgroundCompilation(
1051 1052 1053
    ZoneStats* zone_stats, JSHeapBroker* broker,
    CompilationDependencies* dependencies, CompilationSubject function,
    base::Optional<Hints> new_target, const HintsVector& arguments,
1054
    MissingArgumentsPolicy padding,
1055
    SerializerForBackgroundCompilationFlags flags, int nesting_level)
1056
    : broker_(broker),
1057
      dependencies_(dependencies),
1058
      zone_scope_(zone_stats, ZONE_NAME),
1059 1060 1061 1062
      flags_(flags),
      function_(function.virtual_closure()),
      osr_offset_(BailoutId::None()),
      jump_target_environments_(zone()),
1063 1064 1065
      environment_(zone()->New<Environment>(zone(), broker_->isolate(),
                                            function, new_target, arguments,
                                            padding)),
1066 1067
      arguments_(arguments),
      nesting_level_(nesting_level) {
1068 1069
  Handle<JSFunction> closure;
  if (function.closure().ToHandle(&closure)) {
1070
    closure_hints_.AddConstant(closure, zone(), broker);
1071
    JSFunctionRef(broker, closure).Serialize();
1072
  } else {
1073 1074
    closure_hints_.AddVirtualClosure(function.virtual_closure(), zone(),
                                     broker);
1075
  }
1076 1077 1078

  TRACE_BROKER(broker_, "Hints for <closure>: " << closure_hints_);
  TRACE_BROKER(broker_, "Initial environment:\n" << *environment_);
1079
}
1080

1081
bool SerializerForBackgroundCompilation::BailoutOnUninitialized(
1082
    ProcessedFeedback const& feedback) {
1083 1084 1085 1086 1087
  DCHECK(!environment()->IsDead());
  if (!(flags() &
        SerializerForBackgroundCompilationFlag::kBailoutOnUninitialized)) {
    return false;
  }
1088
  if (!osr_offset().IsNone()) {
1089 1090 1091 1092
    // Exclude OSR from this optimization because we might end up skipping the
    // OSR entry point. TODO(neis): Support OSR?
    return false;
  }
1093 1094 1095
  if (FLAG_turboprop && feedback.slot_kind() == FeedbackSlotKind::kCall) {
    return false;
  }
1096
  if (feedback.IsInsufficient()) {
1097 1098 1099 1100 1101 1102
    environment()->Kill();
    return true;
  }
  return false;
}

1103
Hints SerializerForBackgroundCompilation::Run() {
1104
  TraceScope tracer(broker(), this, "SerializerForBackgroundCompilation::Run");
1105 1106 1107 1108 1109 1110 1111 1112
  if (nesting_level_ >= FLAG_max_serializer_nesting) {
    TRACE_BROKER_MISSING(
        broker(),
        "opportunity - Reached max nesting level for "
        "SerializerForBackgroundCompilation::Run, bailing out.\n");
    return Hints();
  }

1113 1114
  TRACE_BROKER_MEMORY(broker(), "[serializer start] Broker zone usage: "
                                    << broker()->zone()->allocation_size());
1115
  SharedFunctionInfoRef shared(broker(), function().shared());
1116
  FeedbackVectorRef feedback_vector_ref(broker(), feedback_vector());
1117 1118
  if (!broker()->ShouldBeSerializedForCompilation(shared, feedback_vector_ref,
                                                  arguments_)) {
1119 1120 1121
    TRACE_BROKER(broker(),
                 "opportunity - Already ran serializer for SharedFunctionInfo "
                     << Brief(*shared.object()) << ", bailing out.\n");
1122
    return Hints();
1123
  }
1124 1125 1126 1127 1128

  {
    HintsVector arguments_copy_in_broker_zone(broker()->zone());
    for (auto const& hints : arguments_) {
      arguments_copy_in_broker_zone.push_back(
1129
          hints.CopyToParentZone(broker()->zone(), broker()));
1130 1131 1132 1133
    }
    broker()->SetSerializedForCompilation(shared, feedback_vector_ref,
                                          arguments_copy_in_broker_zone);
  }
1134 1135 1136 1137

  // We eagerly call the {EnsureSourcePositionsAvailable} for all serialized
  // SFIs while still on the main thread. Source positions will later be used
  // by JSInliner::ReduceJSCall.
1138 1139
  if (flags() &
      SerializerForBackgroundCompilationFlag::kCollectSourcePositions) {
1140 1141 1142 1143
    SharedFunctionInfo::EnsureSourcePositionsAvailable(broker()->isolate(),
                                                       shared.object());
  }

1144
  feedback_vector_ref.Serialize();
1145
  TraverseBytecode();
1146

1147 1148 1149
  if (return_value_hints().IsEmpty()) {
    TRACE_BROKER(broker(), "Return value hints: none");
  } else {
1150
    TRACE_BROKER(broker(), "Return value hints: " << return_value_hints());
1151
  }
1152 1153
  TRACE_BROKER_MEMORY(broker(), "[serializer end] Broker zone usage: "
                                    << broker()->zone()->allocation_size());
1154
  return return_value_hints();
1155
}
1156

1157
class HandlerRangeMatcher {
1158
 public:
1159 1160
  HandlerRangeMatcher(BytecodeArrayIterator const& bytecode_iterator,
                      Handle<BytecodeArray> bytecode_array)
1161
      : bytecode_iterator_(bytecode_iterator) {
1162
    HandlerTable table(*bytecode_array);
1163
    for (int i = 0, n = table.NumberOfRangeEntries(); i < n; ++i) {
1164 1165
      ranges_.insert({table.GetRangeStart(i), table.GetRangeEnd(i),
                      table.GetRangeHandler(i)});
1166
    }
1167
    ranges_iterator_ = ranges_.cbegin();
1168 1169
  }

1170 1171 1172
  using OffsetReporter = std::function<void(int handler_offset)>;

  void HandlerOffsetForCurrentPosition(const OffsetReporter& offset_reporter) {
1173
    CHECK(!bytecode_iterator_.done());
1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186
    const int current_offset = bytecode_iterator_.current_offset();

    // Remove outdated try ranges from the stack.
    while (!stack_.empty()) {
      const int end = stack_.top().end;
      if (end < current_offset) {
        stack_.pop();
      } else {
        break;
      }
    }

    // Advance the iterator and maintain the stack.
1187
    while (ranges_iterator_ != ranges_.cend() &&
1188 1189 1190 1191 1192 1193 1194
           ranges_iterator_->start <= current_offset) {
      if (ranges_iterator_->end >= current_offset) {
        stack_.push(*ranges_iterator_);
        if (ranges_iterator_->start == current_offset) {
          offset_reporter(ranges_iterator_->handler);
        }
      }
1195 1196
      ranges_iterator_++;
    }
1197 1198 1199

    if (!stack_.empty() && stack_.top().start < current_offset) {
      offset_reporter(stack_.top().handler);
1200 1201 1202 1203 1204
    }
  }

 private:
  BytecodeArrayIterator const& bytecode_iterator_;
1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221

  struct Range {
    int start;
    int end;
    int handler;
    friend bool operator<(const Range& a, const Range& b) {
      if (a.start < b.start) return true;
      if (a.start == b.start) {
        if (a.end < b.end) return true;
        CHECK_GT(a.end, b.end);
      }
      return false;
    }
  };
  std::set<Range> ranges_;
  std::set<Range>::const_iterator ranges_iterator_;
  std::stack<Range> stack_;
1222 1223
};

1224 1225
Handle<FeedbackVector> SerializerForBackgroundCompilation::feedback_vector()
    const {
1226
  return function().feedback_vector();
1227 1228
}

1229 1230
Handle<BytecodeArray> SerializerForBackgroundCompilation::bytecode_array()
    const {
1231
  return handle(function().shared()->GetBytecodeArray(), broker()->isolate());
1232 1233 1234
}

BytecodeAnalysis const& SerializerForBackgroundCompilation::GetBytecodeAnalysis(
1235
    SerializationPolicy policy) {
1236 1237
  return broker()->GetBytecodeAnalysis(
      bytecode_array(), osr_offset(),
1238 1239
      flags() &
          SerializerForBackgroundCompilationFlag::kAnalyzeEnvironmentLiveness,
1240
      policy);
1241 1242 1243
}

void SerializerForBackgroundCompilation::TraverseBytecode() {
1244 1245
  BytecodeAnalysis const& bytecode_analysis =
      GetBytecodeAnalysis(SerializationPolicy::kSerializeIfNeeded);
1246 1247 1248
  BytecodeArrayRef(broker(), bytecode_array()).SerializeForCompilation();

  BytecodeArrayIterator iterator(bytecode_array());
1249
  HandlerRangeMatcher try_start_matcher(iterator, bytecode_array());
1250

1251
  bool has_one_shot_bytecode = false;
1252
  for (; !iterator.done(); iterator.Advance()) {
1253 1254 1255 1256
    has_one_shot_bytecode =
        has_one_shot_bytecode ||
        interpreter::Bytecodes::IsOneShotBytecode(iterator.current_bytecode());

1257
    int const current_offset = iterator.current_offset();
1258 1259 1260

    // TODO(mvstanton): we might want to ignore the current environment if we
    // are at the start of a catch handler.
1261
    IncorporateJumpTargetEnvironment(current_offset);
1262

1263
    TRACE_BROKER(broker(),
1264
                 "Handling bytecode: " << current_offset << "  "
1265 1266 1267
                                       << iterator.current_bytecode());
    TRACE_BROKER(broker(), "Current environment: " << *environment());

1268
    if (environment()->IsDead()) {
1269 1270 1271
      continue;  // Skip this bytecode since TF won't generate code for it.
    }

1272 1273 1274 1275 1276 1277 1278 1279 1280 1281
    auto save_handler_environments = [&](int handler_offset) {
      auto it = jump_target_environments_.find(handler_offset);
      if (it == jump_target_environments_.end()) {
        ContributeToJumpTargetEnvironment(handler_offset);
        TRACE_BROKER(broker(),
                     "Handler offset for current pos: " << handler_offset);
      }
    };
    try_start_matcher.HandlerOffsetForCurrentPosition(
        save_handler_environments);
1282

1283 1284 1285 1286 1287 1288 1289 1290 1291
    if (bytecode_analysis.IsLoopHeader(current_offset)) {
      // Graph builder might insert jumps to resume targets in the loop body.
      LoopInfo const& loop_info =
          bytecode_analysis.GetLoopInfoFor(current_offset);
      for (const auto& target : loop_info.resume_jump_targets()) {
        ContributeToJumpTargetEnvironment(target.target_offset());
      }
    }

1292
    switch (iterator.current_bytecode()) {
1293 1294
#define DEFINE_BYTECODE_CASE(name)     \
  case interpreter::Bytecode::k##name: \
1295
    Visit##name(&iterator);            \
1296 1297 1298
    break;
      SUPPORTED_BYTECODE_LIST(DEFINE_BYTECODE_CASE)
#undef DEFINE_BYTECODE_CASE
1299
      default:
1300 1301 1302
        break;
    }
  }
1303 1304 1305 1306 1307

  if (has_one_shot_bytecode) {
    broker()->isolate()->CountUsage(
        v8::Isolate::UseCounterFeature::kOptimizedFunctionWithOneShotBytecode);
  }
1308 1309
}

1310 1311
void SerializerForBackgroundCompilation::VisitGetIterator(
    BytecodeArrayIterator* iterator) {
1312
  Hints* receiver = &register_hints(iterator->GetRegisterOperand(0));
1313
  FeedbackSlot load_slot = iterator->GetSlotOperand(1);
1314 1315 1316
  FeedbackSlot call_slot = iterator->GetSlotOperand(2);

  Handle<Name> name = broker()->isolate()->factory()->iterator_symbol();
1317 1318 1319 1320
  ProcessNamedPropertyAccess(receiver, NameRef(broker(), name), load_slot,
                             AccessMode::kLoad);
  if (environment()->IsDead()) return;

1321 1322 1323 1324
  Hints callee;
  HintsVector args = PrepareArgumentsHints(receiver);

  ProcessCallOrConstruct(callee, base::nullopt, &args, call_slot,
1325
                         kMissingArgumentsAreUndefined);
1326 1327
}

1328 1329 1330
void SerializerForBackgroundCompilation::VisitGetSuperConstructor(
    BytecodeArrayIterator* iterator) {
  interpreter::Register dst = iterator->GetRegisterOperand(0);
1331
  Hints result_hints;
1332 1333 1334 1335
  for (auto constant : environment()->accumulator_hints().constants()) {
    // For JSNativeContextSpecialization::ReduceJSGetSuperConstructor.
    if (!constant->IsJSFunction()) continue;
    MapRef map(broker(),
1336
               handle(HeapObject::cast(*constant).map(), broker()->isolate()));
1337 1338 1339
    map.SerializePrototype();
    ObjectRef proto = map.prototype();
    if (proto.IsHeapObject() && proto.AsHeapObject().map().is_constructor()) {
1340
      result_hints.AddConstant(proto.object(), zone(), broker());
1341 1342
    }
  }
1343
  register_hints(dst) = result_hints;
1344 1345
}

1346 1347
void SerializerForBackgroundCompilation::VisitGetTemplateObject(
    BytecodeArrayIterator* iterator) {
1348
  TemplateObjectDescriptionRef description(
1349 1350
      broker(), iterator->GetConstantForIndexOperand(0, broker()->isolate()));
  FeedbackSlot slot = iterator->GetSlotOperand(1);
1351
  FeedbackSource source(feedback_vector(), slot);
1352
  SharedFunctionInfoRef shared(broker(), function().shared());
1353 1354
  JSArrayRef template_object = shared.GetTemplateObject(
      description, source, SerializationPolicy::kSerializeIfNeeded);
1355
  environment()->accumulator_hints() =
1356
      Hints::SingleConstant(template_object.object(), zone());
1357 1358
}

1359 1360
void SerializerForBackgroundCompilation::VisitLdaTrue(
    BytecodeArrayIterator* iterator) {
1361
  environment()->accumulator_hints() = Hints::SingleConstant(
1362
      broker()->isolate()->factory()->true_value(), zone());
1363 1364 1365 1366
}

void SerializerForBackgroundCompilation::VisitLdaFalse(
    BytecodeArrayIterator* iterator) {
1367
  environment()->accumulator_hints() = Hints::SingleConstant(
1368
      broker()->isolate()->factory()->false_value(), zone());
1369 1370 1371 1372
}

void SerializerForBackgroundCompilation::VisitLdaTheHole(
    BytecodeArrayIterator* iterator) {
1373
  environment()->accumulator_hints() = Hints::SingleConstant(
1374
      broker()->isolate()->factory()->the_hole_value(), zone());
1375
}
1376

1377
void SerializerForBackgroundCompilation::VisitLdaUndefined(
1378
    BytecodeArrayIterator* iterator) {
1379
  environment()->accumulator_hints() = Hints::SingleConstant(
1380
      broker()->isolate()->factory()->undefined_value(), zone());
1381 1382 1383
}

void SerializerForBackgroundCompilation::VisitLdaNull(
1384
    BytecodeArrayIterator* iterator) {
1385
  environment()->accumulator_hints() = Hints::SingleConstant(
1386
      broker()->isolate()->factory()->null_value(), zone());
1387 1388 1389
}

void SerializerForBackgroundCompilation::VisitLdaZero(
1390
    BytecodeArrayIterator* iterator) {
1391
  environment()->accumulator_hints() = Hints::SingleConstant(
1392
      handle(Smi::FromInt(0), broker()->isolate()), zone());
1393 1394 1395
}

void SerializerForBackgroundCompilation::VisitLdaSmi(
1396
    BytecodeArrayIterator* iterator) {
1397 1398
  Handle<Smi> smi(Smi::FromInt(iterator->GetImmediateOperand(0)),
                  broker()->isolate());
1399
  environment()->accumulator_hints() = Hints::SingleConstant(smi, zone());
1400 1401
}

1402 1403 1404 1405 1406
void SerializerForBackgroundCompilation::VisitInvokeIntrinsic(
    BytecodeArrayIterator* iterator) {
  Runtime::FunctionId functionId = iterator->GetIntrinsicIdOperand(0);
  // For JSNativeContextSpecialization::ReduceJSAsyncFunctionResolve and
  // JSNativeContextSpecialization::ReduceJSResolvePromise.
1407 1408 1409 1410 1411 1412 1413
  switch (functionId) {
    case Runtime::kInlineAsyncFunctionResolve: {
      ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
                              Builtins::kAsyncFunctionResolve));
      interpreter::Register first_reg = iterator->GetRegisterOperand(1);
      size_t reg_count = iterator->GetRegisterCountOperand(2);
      CHECK_EQ(reg_count, 3);
1414 1415
      HintsVector args = PrepareArgumentsHints(first_reg, reg_count);
      Hints const& resolution_hints = args[1];  // The resolution object.
1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477
      ProcessHintsForPromiseResolve(resolution_hints);
      return;
    }
    case Runtime::kInlineAsyncGeneratorReject:
    case Runtime::kAsyncGeneratorReject: {
      ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
                              Builtins::kAsyncGeneratorReject));
      break;
    }
    case Runtime::kInlineAsyncGeneratorResolve:
    case Runtime::kAsyncGeneratorResolve: {
      ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
                              Builtins::kAsyncGeneratorResolve));
      break;
    }
    case Runtime::kInlineAsyncGeneratorYield:
    case Runtime::kAsyncGeneratorYield: {
      ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
                              Builtins::kAsyncGeneratorYield));
      break;
    }
    case Runtime::kInlineAsyncGeneratorAwaitUncaught:
    case Runtime::kAsyncGeneratorAwaitUncaught: {
      ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
                              Builtins::kAsyncGeneratorAwaitUncaught));
      break;
    }
    case Runtime::kInlineAsyncGeneratorAwaitCaught:
    case Runtime::kAsyncGeneratorAwaitCaught: {
      ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
                              Builtins::kAsyncGeneratorAwaitCaught));
      break;
    }
    case Runtime::kInlineAsyncFunctionAwaitUncaught:
    case Runtime::kAsyncFunctionAwaitUncaught: {
      ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
                              Builtins::kAsyncFunctionAwaitUncaught));
      break;
    }
    case Runtime::kInlineAsyncFunctionAwaitCaught:
    case Runtime::kAsyncFunctionAwaitCaught: {
      ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
                              Builtins::kAsyncFunctionAwaitCaught));
      break;
    }
    case Runtime::kInlineAsyncFunctionReject:
    case Runtime::kAsyncFunctionReject: {
      ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
                              Builtins::kAsyncFunctionReject));
      break;
    }
    case Runtime::kAsyncFunctionResolve: {
      ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
                              Builtins::kAsyncFunctionResolve));
      break;
    }
    case Runtime::kInlineCopyDataProperties:
    case Runtime::kCopyDataProperties: {
      ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
                              Builtins::kCopyDataProperties));
      break;
    }
1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491
    case Runtime::kInlineGetImportMetaObject: {
      Hints const& context_hints = environment()->current_context_hints();
      for (auto x : context_hints.constants()) {
        ContextRef(broker(), x)
            .GetModule(SerializationPolicy::kSerializeIfNeeded)
            .Serialize();
      }
      for (auto x : context_hints.virtual_contexts()) {
        ContextRef(broker(), x.context)
            .GetModule(SerializationPolicy::kSerializeIfNeeded)
            .Serialize();
      }
      break;
    }
1492 1493 1494
    default: {
      break;
    }
1495
  }
1496
  environment()->accumulator_hints() = Hints();
1497 1498
}

1499
void SerializerForBackgroundCompilation::VisitLdaConstant(
1500
    BytecodeArrayIterator* iterator) {
1501 1502
  ObjectRef object(
      broker(), iterator->GetConstantForIndexOperand(0, broker()->isolate()));
1503
  environment()->accumulator_hints() =
1504
      Hints::SingleConstant(object.object(), zone());
1505 1506
}

1507 1508
void SerializerForBackgroundCompilation::VisitPushContext(
    BytecodeArrayIterator* iterator) {
1509
  register_hints(iterator->GetRegisterOperand(0))
1510 1511 1512
      .Reset(&environment()->current_context_hints(), zone());
  environment()->current_context_hints().Reset(
      &environment()->accumulator_hints(), zone());
1513 1514 1515 1516
}

void SerializerForBackgroundCompilation::VisitPopContext(
    BytecodeArrayIterator* iterator) {
1517
  environment()->current_context_hints().Reset(
1518
      &register_hints(iterator->GetRegisterOperand(0)), zone());
1519 1520 1521
}

void SerializerForBackgroundCompilation::ProcessImmutableLoad(
1522
    ContextRef const& context_ref, int slot, ContextProcessingMode mode,
1523
    Hints* result_hints) {
1524 1525 1526
  DCHECK_EQ(mode, kSerializeSlot);
  base::Optional<ObjectRef> slot_value =
      context_ref.get(slot, SerializationPolicy::kSerializeIfNeeded);
1527

1528 1529
  // If requested, record the object as a hint for the result value.
  if (result_hints != nullptr && slot_value.has_value()) {
1530
    result_hints->AddConstant(slot_value.value().object(), zone(), broker());
1531 1532 1533 1534
  }
}

void SerializerForBackgroundCompilation::ProcessContextAccess(
1535
    Hints const& context_hints, int slot, int depth, ContextProcessingMode mode,
1536
    Hints* result_hints) {
1537 1538 1539 1540 1541 1542 1543 1544 1545
  // This function is for JSContextSpecialization::ReduceJSLoadContext and
  // ReduceJSStoreContext. Those reductions attempt to eliminate as many
  // loads as possible by making use of constant Context objects. In the
  // case of an immutable load, ReduceJSLoadContext even attempts to load
  // the value at {slot}, replacing the load with a constant.
  for (auto x : context_hints.constants()) {
    if (x->IsContext()) {
      // Walk this context to the given depth and serialize the slot found.
      ContextRef context_ref(broker(), x);
1546
      size_t remaining_depth = depth;
1547 1548
      context_ref = context_ref.previous(
          &remaining_depth, SerializationPolicy::kSerializeIfNeeded);
1549
      if (remaining_depth == 0 && mode != kIgnoreSlot) {
1550
        ProcessImmutableLoad(context_ref, slot, mode, result_hints);
1551 1552 1553 1554 1555 1556
      }
    }
  }
  for (auto x : context_hints.virtual_contexts()) {
    if (x.distance <= static_cast<unsigned int>(depth)) {
      ContextRef context_ref(broker(), x.context);
1557
      size_t remaining_depth = depth - x.distance;
1558 1559
      context_ref = context_ref.previous(
          &remaining_depth, SerializationPolicy::kSerializeIfNeeded);
1560
      if (remaining_depth == 0 && mode != kIgnoreSlot) {
1561
        ProcessImmutableLoad(context_ref, slot, mode, result_hints);
1562 1563 1564 1565 1566 1567 1568
      }
    }
  }
}

void SerializerForBackgroundCompilation::VisitLdaContextSlot(
    BytecodeArrayIterator* iterator) {
1569
  Hints const& context_hints = register_hints(iterator->GetRegisterOperand(0));
1570 1571
  const int slot = iterator->GetIndexOperand(1);
  const int depth = iterator->GetUnsignedImmediateOperand(2);
1572
  Hints new_accumulator_hints;
1573 1574
  ProcessContextAccess(context_hints, slot, depth, kIgnoreSlot,
                       &new_accumulator_hints);
1575
  environment()->accumulator_hints() = new_accumulator_hints;
1576 1577 1578 1579 1580 1581
}

void SerializerForBackgroundCompilation::VisitLdaCurrentContextSlot(
    BytecodeArrayIterator* iterator) {
  const int slot = iterator->GetIndexOperand(0);
  const int depth = 0;
1582
  Hints const& context_hints = environment()->current_context_hints();
1583
  Hints new_accumulator_hints;
1584 1585
  ProcessContextAccess(context_hints, slot, depth, kIgnoreSlot,
                       &new_accumulator_hints);
1586
  environment()->accumulator_hints() = new_accumulator_hints;
1587 1588 1589 1590 1591 1592
}

void SerializerForBackgroundCompilation::VisitLdaImmutableContextSlot(
    BytecodeArrayIterator* iterator) {
  const int slot = iterator->GetIndexOperand(1);
  const int depth = iterator->GetUnsignedImmediateOperand(2);
1593
  Hints const& context_hints = register_hints(iterator->GetRegisterOperand(0));
1594
  Hints new_accumulator_hints;
1595 1596
  ProcessContextAccess(context_hints, slot, depth, kSerializeSlot,
                       &new_accumulator_hints);
1597
  environment()->accumulator_hints() = new_accumulator_hints;
1598 1599 1600 1601 1602 1603
}

void SerializerForBackgroundCompilation::VisitLdaImmutableCurrentContextSlot(
    BytecodeArrayIterator* iterator) {
  const int slot = iterator->GetIndexOperand(0);
  const int depth = 0;
1604
  Hints const& context_hints = environment()->current_context_hints();
1605
  Hints new_accumulator_hints;
1606 1607
  ProcessContextAccess(context_hints, slot, depth, kSerializeSlot,
                       &new_accumulator_hints);
1608
  environment()->accumulator_hints() = new_accumulator_hints;
1609 1610
}

1611
void SerializerForBackgroundCompilation::ProcessModuleVariableAccess(
1612
    BytecodeArrayIterator* iterator) {
1613
  const int slot = Context::EXTENSION_INDEX;
1614
  const int depth = iterator->GetUnsignedImmediateOperand(1);
1615
  Hints const& context_hints = environment()->current_context_hints();
1616

1617
  Hints result_hints;
1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629
  ProcessContextAccess(context_hints, slot, depth, kSerializeSlot,
                       &result_hints);
  for (Handle<Object> constant : result_hints.constants()) {
    ObjectRef object(broker(), constant);
    // For JSTypedLowering::BuildGetModuleCell.
    if (object.IsSourceTextModule()) object.AsSourceTextModule().Serialize();
  }
}

void SerializerForBackgroundCompilation::VisitLdaModuleVariable(
    BytecodeArrayIterator* iterator) {
  ProcessModuleVariableAccess(iterator);
1630 1631 1632 1633
}

void SerializerForBackgroundCompilation::VisitStaModuleVariable(
    BytecodeArrayIterator* iterator) {
1634
  ProcessModuleVariableAccess(iterator);
1635 1636
}

1637 1638 1639 1640
void SerializerForBackgroundCompilation::VisitStaLookupSlot(
    BytecodeArrayIterator* iterator) {
  ObjectRef(broker(),
            iterator->GetConstantForIndexOperand(0, broker()->isolate()));
1641
  environment()->accumulator_hints() = Hints();
1642 1643
}

1644 1645 1646 1647
void SerializerForBackgroundCompilation::VisitStaContextSlot(
    BytecodeArrayIterator* iterator) {
  const int slot = iterator->GetIndexOperand(1);
  const int depth = iterator->GetUnsignedImmediateOperand(2);
1648 1649
  Hints const& hints = register_hints(iterator->GetRegisterOperand(0));
  ProcessContextAccess(hints, slot, depth, kIgnoreSlot);
1650 1651 1652 1653 1654 1655
}

void SerializerForBackgroundCompilation::VisitStaCurrentContextSlot(
    BytecodeArrayIterator* iterator) {
  const int slot = iterator->GetIndexOperand(0);
  const int depth = 0;
1656
  Hints const& context_hints = environment()->current_context_hints();
1657 1658 1659
  ProcessContextAccess(context_hints, slot, depth, kIgnoreSlot);
}

1660
void SerializerForBackgroundCompilation::VisitLdar(
1661
    BytecodeArrayIterator* iterator) {
1662
  environment()->accumulator_hints().Reset(
1663
      &register_hints(iterator->GetRegisterOperand(0)), zone());
1664 1665 1666
}

void SerializerForBackgroundCompilation::VisitStar(
1667
    BytecodeArrayIterator* iterator) {
1668
  interpreter::Register reg = iterator->GetRegisterOperand(0);
1669
  register_hints(reg).Reset(&environment()->accumulator_hints(), zone());
1670 1671 1672
}

void SerializerForBackgroundCompilation::VisitMov(
1673
    BytecodeArrayIterator* iterator) {
1674 1675
  interpreter::Register src = iterator->GetRegisterOperand(0);
  interpreter::Register dst = iterator->GetRegisterOperand(1);
1676
  register_hints(dst).Reset(&register_hints(src), zone());
1677 1678
}

1679 1680 1681 1682 1683
void SerializerForBackgroundCompilation::VisitCreateRegExpLiteral(
    BytecodeArrayIterator* iterator) {
  Handle<String> constant_pattern = Handle<String>::cast(
      iterator->GetConstantForIndexOperand(0, broker()->isolate()));
  StringRef description(broker(), constant_pattern);
1684 1685 1686
  FeedbackSlot slot = iterator->GetSlotOperand(1);
  FeedbackSource source(feedback_vector(), slot);
  broker()->ProcessFeedbackForRegExpLiteral(source);
1687
  environment()->accumulator_hints() = Hints();
1688 1689 1690 1691 1692 1693 1694 1695 1696
}

void SerializerForBackgroundCompilation::VisitCreateArrayLiteral(
    BytecodeArrayIterator* iterator) {
  Handle<ArrayBoilerplateDescription> array_boilerplate_description =
      Handle<ArrayBoilerplateDescription>::cast(
          iterator->GetConstantForIndexOperand(0, broker()->isolate()));
  ArrayBoilerplateDescriptionRef description(broker(),
                                             array_boilerplate_description);
1697 1698 1699
  FeedbackSlot slot = iterator->GetSlotOperand(1);
  FeedbackSource source(feedback_vector(), slot);
  broker()->ProcessFeedbackForArrayOrObjectLiteral(source);
1700
  environment()->accumulator_hints() = Hints();
1701 1702 1703 1704 1705 1706 1707
}

void SerializerForBackgroundCompilation::VisitCreateEmptyArrayLiteral(
    BytecodeArrayIterator* iterator) {
  FeedbackSlot slot = iterator->GetSlotOperand(0);
  FeedbackSource source(feedback_vector(), slot);
  broker()->ProcessFeedbackForArrayOrObjectLiteral(source);
1708
  environment()->accumulator_hints() = Hints();
1709 1710 1711 1712 1713 1714 1715 1716
}

void SerializerForBackgroundCompilation::VisitCreateObjectLiteral(
    BytecodeArrayIterator* iterator) {
  Handle<ObjectBoilerplateDescription> constant_properties =
      Handle<ObjectBoilerplateDescription>::cast(
          iterator->GetConstantForIndexOperand(0, broker()->isolate()));
  ObjectBoilerplateDescriptionRef description(broker(), constant_properties);
1717 1718 1719
  FeedbackSlot slot = iterator->GetSlotOperand(1);
  FeedbackSource source(feedback_vector(), slot);
  broker()->ProcessFeedbackForArrayOrObjectLiteral(source);
1720
  environment()->accumulator_hints() = Hints();
1721 1722
}

1723 1724
void SerializerForBackgroundCompilation::VisitCreateFunctionContext(
    BytecodeArrayIterator* iterator) {
1725
  ProcessCreateContext(iterator, 0);
1726 1727 1728 1729
}

void SerializerForBackgroundCompilation::VisitCreateBlockContext(
    BytecodeArrayIterator* iterator) {
1730
  ProcessCreateContext(iterator, 0);
1731 1732 1733 1734
}

void SerializerForBackgroundCompilation::VisitCreateEvalContext(
    BytecodeArrayIterator* iterator) {
1735
  ProcessCreateContext(iterator, 0);
1736 1737 1738 1739
}

void SerializerForBackgroundCompilation::VisitCreateWithContext(
    BytecodeArrayIterator* iterator) {
1740
  ProcessCreateContext(iterator, 1);
1741 1742 1743 1744
}

void SerializerForBackgroundCompilation::VisitCreateCatchContext(
    BytecodeArrayIterator* iterator) {
1745
  ProcessCreateContext(iterator, 1);
1746 1747
}

1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759
void SerializerForBackgroundCompilation::VisitForInNext(
    BytecodeArrayIterator* iterator) {
  FeedbackSlot slot = iterator->GetSlotOperand(3);
  ProcessForIn(slot);
}

void SerializerForBackgroundCompilation::VisitForInPrepare(
    BytecodeArrayIterator* iterator) {
  FeedbackSlot slot = iterator->GetSlotOperand(1);
  ProcessForIn(slot);
}

1760 1761 1762 1763 1764 1765
void SerializerForBackgroundCompilation::ProcessCreateContext(
    interpreter::BytecodeArrayIterator* iterator, int scopeinfo_operand_index) {
  Handle<ScopeInfo> scope_info =
      Handle<ScopeInfo>::cast(iterator->GetConstantForIndexOperand(
          scopeinfo_operand_index, broker()->isolate()));
  ScopeInfoRef scope_info_ref(broker(), scope_info);
1766
  scope_info_ref.SerializeScopeInfoChain();
1767

1768
  Hints const& current_context_hints = environment()->current_context_hints();
1769
  Hints result_hints;
1770 1771 1772 1773 1774 1775

  // For each constant context, we must create a virtual context from
  // it of distance one.
  for (auto x : current_context_hints.constants()) {
    if (x->IsContext()) {
      Handle<Context> as_context(Handle<Context>::cast(x));
1776 1777
      result_hints.AddVirtualContext(VirtualContext(1, as_context), zone(),
                                     broker());
1778 1779 1780 1781 1782 1783
    }
  }

  // For each virtual context, we must create a virtual context from
  // it of distance {existing distance} + 1.
  for (auto x : current_context_hints.virtual_contexts()) {
1784
    result_hints.AddVirtualContext(VirtualContext(x.distance + 1, x.context),
1785
                                   zone(), broker());
1786
  }
1787 1788

  environment()->accumulator_hints() = result_hints;
1789 1790
}

1791
void SerializerForBackgroundCompilation::VisitCreateClosure(
1792
    BytecodeArrayIterator* iterator) {
1793 1794
  Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(
      iterator->GetConstantForIndexOperand(0, broker()->isolate()));
1795
  Handle<FeedbackCell> feedback_cell =
1796
      feedback_vector()->GetClosureFeedbackCell(iterator->GetIndexOperand(1));
1797
  FeedbackCellRef feedback_cell_ref(broker(), feedback_cell);
1798
  Handle<Object> cell_value(feedback_cell->value(), broker()->isolate());
1799
  ObjectRef cell_value_ref(broker(), cell_value);
1800

1801
  Hints result_hints;
1802
  if (cell_value->IsFeedbackVector()) {
1803 1804 1805
    VirtualClosure virtual_closure(shared,
                                   Handle<FeedbackVector>::cast(cell_value),
                                   environment()->current_context_hints());
1806
    result_hints.AddVirtualClosure(virtual_closure, zone(), broker());
1807
  }
1808
  environment()->accumulator_hints() = result_hints;
1809 1810 1811
}

void SerializerForBackgroundCompilation::VisitCallUndefinedReceiver(
1812
    BytecodeArrayIterator* iterator) {
1813
  Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
1814 1815 1816 1817 1818
  interpreter::Register first_reg = iterator->GetRegisterOperand(1);
  int reg_count = static_cast<int>(iterator->GetRegisterCountOperand(2));
  FeedbackSlot slot = iterator->GetSlotOperand(3);
  ProcessCallVarArgs(ConvertReceiverMode::kNullOrUndefined, callee, first_reg,
                     reg_count, slot);
1819 1820 1821
}

void SerializerForBackgroundCompilation::VisitCallUndefinedReceiver0(
1822
    BytecodeArrayIterator* iterator) {
1823
  Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
1824
  FeedbackSlot slot = iterator->GetSlotOperand(1);
1825

1826
  Hints const receiver = Hints::SingleConstant(
1827
      broker()->isolate()->factory()->undefined_value(), zone());
1828
  HintsVector parameters({receiver}, zone());
1829

1830
  ProcessCallOrConstruct(callee, base::nullopt, &parameters, slot,
1831
                         kMissingArgumentsAreUndefined);
1832 1833
}

1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858
namespace {
void PrepareArgumentsHintsInternal(Zone* zone, HintsVector* args) {}

template <typename... MoreHints>
void PrepareArgumentsHintsInternal(Zone* zone, HintsVector* args, Hints* hints,
                                   MoreHints... more) {
  hints->EnsureShareable(zone);
  args->push_back(*hints);
  PrepareArgumentsHintsInternal(zone, args, more...);
}
}  // namespace

template <typename... MoreHints>
HintsVector SerializerForBackgroundCompilation::PrepareArgumentsHints(
    Hints* hints, MoreHints... more) {
  HintsVector args(zone());
  PrepareArgumentsHintsInternal(zone(), &args, hints, more...);
  return args;
}

HintsVector SerializerForBackgroundCompilation::PrepareArgumentsHints(
    interpreter::Register first, size_t count) {
  HintsVector result(zone());
  const int reg_base = first.index();
  for (int i = 0; i < static_cast<int>(count); ++i) {
1859
    Hints& hints = register_hints(interpreter::Register(reg_base + i));
1860 1861 1862 1863 1864 1865
    hints.EnsureShareable(zone());
    result.push_back(hints);
  }
  return result;
}

1866
void SerializerForBackgroundCompilation::VisitCallUndefinedReceiver1(
1867
    BytecodeArrayIterator* iterator) {
1868 1869
  Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
  Hints* arg0 = &register_hints(iterator->GetRegisterOperand(1));
1870
  FeedbackSlot slot = iterator->GetSlotOperand(2);
1871

1872
  Hints receiver = Hints::SingleConstant(
1873
      broker()->isolate()->factory()->undefined_value(), zone());
1874 1875 1876
  HintsVector args = PrepareArgumentsHints(&receiver, arg0);

  ProcessCallOrConstruct(callee, base::nullopt, &args, slot,
1877
                         kMissingArgumentsAreUndefined);
1878 1879 1880
}

void SerializerForBackgroundCompilation::VisitCallUndefinedReceiver2(
1881
    BytecodeArrayIterator* iterator) {
1882 1883 1884
  Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
  Hints* arg0 = &register_hints(iterator->GetRegisterOperand(1));
  Hints* arg1 = &register_hints(iterator->GetRegisterOperand(2));
1885
  FeedbackSlot slot = iterator->GetSlotOperand(3);
1886

1887
  Hints receiver = Hints::SingleConstant(
1888
      broker()->isolate()->factory()->undefined_value(), zone());
1889 1890 1891
  HintsVector args = PrepareArgumentsHints(&receiver, arg0, arg1);

  ProcessCallOrConstruct(callee, base::nullopt, &args, slot,
1892
                         kMissingArgumentsAreUndefined);
1893 1894 1895
}

void SerializerForBackgroundCompilation::VisitCallAnyReceiver(
1896
    BytecodeArrayIterator* iterator) {
1897
  Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
1898 1899 1900 1901 1902 1903 1904 1905 1906
  interpreter::Register first_reg = iterator->GetRegisterOperand(1);
  int reg_count = static_cast<int>(iterator->GetRegisterCountOperand(2));
  FeedbackSlot slot = iterator->GetSlotOperand(3);
  ProcessCallVarArgs(ConvertReceiverMode::kAny, callee, first_reg, reg_count,
                     slot);
}

void SerializerForBackgroundCompilation::VisitCallNoFeedback(
    BytecodeArrayIterator* iterator) {
1907
  Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
1908 1909 1910 1911
  interpreter::Register first_reg = iterator->GetRegisterOperand(1);
  int reg_count = static_cast<int>(iterator->GetRegisterCountOperand(2));
  ProcessCallVarArgs(ConvertReceiverMode::kAny, callee, first_reg, reg_count,
                     FeedbackSlot::Invalid());
1912 1913 1914
}

void SerializerForBackgroundCompilation::VisitCallProperty(
1915
    BytecodeArrayIterator* iterator) {
1916
  Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
1917 1918 1919 1920 1921
  interpreter::Register first_reg = iterator->GetRegisterOperand(1);
  int reg_count = static_cast<int>(iterator->GetRegisterCountOperand(2));
  FeedbackSlot slot = iterator->GetSlotOperand(3);
  ProcessCallVarArgs(ConvertReceiverMode::kNotNullOrUndefined, callee,
                     first_reg, reg_count, slot);
1922 1923 1924
}

void SerializerForBackgroundCompilation::VisitCallProperty0(
1925
    BytecodeArrayIterator* iterator) {
1926 1927
  Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
  Hints* receiver = &register_hints(iterator->GetRegisterOperand(1));
1928
  FeedbackSlot slot = iterator->GetSlotOperand(2);
1929

1930 1931 1932
  HintsVector args = PrepareArgumentsHints(receiver);

  ProcessCallOrConstruct(callee, base::nullopt, &args, slot,
1933
                         kMissingArgumentsAreUndefined);
1934 1935 1936
}

void SerializerForBackgroundCompilation::VisitCallProperty1(
1937
    BytecodeArrayIterator* iterator) {
1938 1939 1940
  Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
  Hints* receiver = &register_hints(iterator->GetRegisterOperand(1));
  Hints* arg0 = &register_hints(iterator->GetRegisterOperand(2));
1941
  FeedbackSlot slot = iterator->GetSlotOperand(3);
1942

1943 1944 1945
  HintsVector args = PrepareArgumentsHints(receiver, arg0);

  ProcessCallOrConstruct(callee, base::nullopt, &args, slot,
1946
                         kMissingArgumentsAreUndefined);
1947 1948 1949
}

void SerializerForBackgroundCompilation::VisitCallProperty2(
1950
    BytecodeArrayIterator* iterator) {
1951 1952 1953 1954
  Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
  Hints* receiver = &register_hints(iterator->GetRegisterOperand(1));
  Hints* arg0 = &register_hints(iterator->GetRegisterOperand(2));
  Hints* arg1 = &register_hints(iterator->GetRegisterOperand(3));
1955
  FeedbackSlot slot = iterator->GetSlotOperand(4);
1956

1957 1958 1959
  HintsVector args = PrepareArgumentsHints(receiver, arg0, arg1);

  ProcessCallOrConstruct(callee, base::nullopt, &args, slot,
1960
                         kMissingArgumentsAreUndefined);
1961 1962
}

1963
void SerializerForBackgroundCompilation::VisitCallWithSpread(
1964
    BytecodeArrayIterator* iterator) {
1965
  Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
1966 1967 1968 1969
  interpreter::Register first_reg = iterator->GetRegisterOperand(1);
  int reg_count = static_cast<int>(iterator->GetRegisterCountOperand(2));
  FeedbackSlot slot = iterator->GetSlotOperand(3);
  ProcessCallVarArgs(ConvertReceiverMode::kAny, callee, first_reg, reg_count,
1970
                     slot, kMissingArgumentsAreUnknown);
1971 1972
}

1973 1974 1975
void SerializerForBackgroundCompilation::VisitCallJSRuntime(
    BytecodeArrayIterator* iterator) {
  const int runtime_index = iterator->GetNativeContextIndexOperand(0);
1976 1977 1978 1979 1980
  ObjectRef constant =
      broker()
          ->target_native_context()
          .get(runtime_index, SerializationPolicy::kSerializeIfNeeded)
          .value();
1981
  Hints const callee = Hints::SingleConstant(constant.object(), zone());
1982 1983 1984 1985
  interpreter::Register first_reg = iterator->GetRegisterOperand(1);
  int reg_count = static_cast<int>(iterator->GetRegisterCountOperand(2));
  ProcessCallVarArgs(ConvertReceiverMode::kNullOrUndefined, callee, first_reg,
                     reg_count, FeedbackSlot::Invalid());
1986 1987
}

1988
Hints SerializerForBackgroundCompilation::RunChildSerializer(
1989
    CompilationSubject function, base::Optional<Hints> new_target,
1990 1991 1992
    const HintsVector& arguments, MissingArgumentsPolicy padding) {
  SerializerForBackgroundCompilation child_serializer(
      zone_scope_.zone_stats(), broker(), dependencies(), function, new_target,
1993
      arguments, padding, flags(), nesting_level_ + 1);
1994
  Hints result = child_serializer.Run();
1995 1996 1997
  // The Hints returned by the call to Run are allocated in the zone
  // created by the child serializer. Adding those hints to a hints
  // object created in our zone will preserve the information.
1998
  return result.CopyToParentZone(zone(), broker());
1999 2000
}

2001
void SerializerForBackgroundCompilation::ProcessCalleeForCallOrConstruct(
2002 2003
    Callee const& callee, base::Optional<Hints> new_target,
    const HintsVector& arguments, SpeculationMode speculation_mode,
2004
    MissingArgumentsPolicy padding, Hints* result_hints) {
2005
  Handle<SharedFunctionInfo> shared = callee.shared(broker()->isolate());
2006 2007
  if (shared->IsApiFunction()) {
    ProcessApiCall(shared, arguments);
2008
    DCHECK_NE(shared->GetInlineability(), SharedFunctionInfo::kIsInlineable);
2009
  } else if (shared->HasBuiltinId()) {
2010 2011
    ProcessBuiltinCall(shared, new_target, arguments, speculation_mode, padding,
                       result_hints);
2012
    DCHECK_NE(shared->GetInlineability(), SharedFunctionInfo::kIsInlineable);
2013 2014 2015
  } else if ((flags() &
              SerializerForBackgroundCompilationFlag::kEnableTurboInlining) &&
             shared->GetInlineability() == SharedFunctionInfo::kIsInlineable &&
2016
             callee.HasFeedbackVector()) {
2017
    CompilationSubject subject =
2018
        callee.ToCompilationSubject(broker()->isolate(), zone());
2019
    result_hints->Add(
2020 2021
        RunChildSerializer(subject, new_target, arguments, padding), zone(),
        broker());
2022 2023 2024 2025
  }
}

namespace {
2026 2027 2028 2029 2030
// Returns the innermost bound target and inserts all bound arguments and
// {original_arguments} into {expanded_arguments} in the appropriate order.
JSReceiverRef UnrollBoundFunction(JSBoundFunctionRef const& bound_function,
                                  JSHeapBroker* broker,
                                  const HintsVector& original_arguments,
2031
                                  HintsVector* expanded_arguments, Zone* zone) {
2032 2033 2034
  DCHECK(expanded_arguments->empty());

  JSReceiverRef target = bound_function.AsJSReceiver();
2035
  HintsVector reversed_bound_arguments(zone);
2036 2037 2038 2039
  for (; target.IsJSBoundFunction();
       target = target.AsJSBoundFunction().bound_target_function()) {
    for (int i = target.AsJSBoundFunction().bound_arguments().length() - 1;
         i >= 0; --i) {
2040
      Hints const arg = Hints::SingleConstant(
2041
          target.AsJSBoundFunction().bound_arguments().get(i).object(), zone);
2042 2043
      reversed_bound_arguments.push_back(arg);
    }
2044
    Hints const arg = Hints::SingleConstant(
2045
        target.AsJSBoundFunction().bound_this().object(), zone);
2046 2047 2048 2049 2050 2051 2052 2053 2054 2055
    reversed_bound_arguments.push_back(arg);
  }

  expanded_arguments->insert(expanded_arguments->end(),
                             reversed_bound_arguments.rbegin(),
                             reversed_bound_arguments.rend());
  expanded_arguments->insert(expanded_arguments->end(),
                             original_arguments.begin(),
                             original_arguments.end());

2056
  return target;
2057
}
2058 2059
}  // namespace

2060 2061 2062
void SerializerForBackgroundCompilation::ProcessCalleeForCallOrConstruct(
    Handle<Object> callee, base::Optional<Hints> new_target,
    const HintsVector& arguments, SpeculationMode speculation_mode,
2063
    MissingArgumentsPolicy padding, Hints* result_hints) {
2064 2065 2066 2067 2068 2069 2070
  const HintsVector* actual_arguments = &arguments;
  HintsVector expanded_arguments(zone());
  if (callee->IsJSBoundFunction()) {
    JSBoundFunctionRef bound_function(broker(),
                                      Handle<JSBoundFunction>::cast(callee));
    bound_function.Serialize();
    callee = UnrollBoundFunction(bound_function, broker(), arguments,
2071
                                 &expanded_arguments, zone())
2072 2073 2074 2075 2076 2077 2078 2079
                 .object();
    actual_arguments = &expanded_arguments;
  }
  if (!callee->IsJSFunction()) return;

  JSFunctionRef function(broker(), Handle<JSFunction>::cast(callee));
  function.Serialize();
  Callee new_callee(function.object());
2080
  ProcessCalleeForCallOrConstruct(new_callee, new_target, *actual_arguments,
2081
                                  speculation_mode, padding, result_hints);
2082 2083
}

2084
void SerializerForBackgroundCompilation::ProcessCallOrConstruct(
2085 2086
    Hints callee, base::Optional<Hints> new_target, HintsVector* arguments,
    FeedbackSlot slot, MissingArgumentsPolicy padding) {
2087
  SpeculationMode speculation_mode = SpeculationMode::kDisallowSpeculation;
2088

2089 2090 2091 2092 2093 2094 2095
  if (!slot.IsInvalid()) {
    FeedbackSource source(feedback_vector(), slot);
    ProcessedFeedback const& feedback =
        broker()->ProcessFeedbackForCall(source);
    if (BailoutOnUninitialized(feedback)) return;

    if (!feedback.IsInsufficient()) {
2096 2097
      // Incorporate feedback into hints copy to simplify processing.
      // TODO(neis): Modify the original hints instead?
2098
      speculation_mode = feedback.AsCall().speculation_mode();
2099
      // Incorporate target feedback into hints copy to simplify processing.
2100
      base::Optional<HeapObjectRef> target = feedback.AsCall().target();
2101 2102
      if (target.has_value() &&
          (target->map().is_callable() || target->IsFeedbackCell())) {
2103
        callee = callee.Copy(zone());
2104 2105 2106 2107
        // TODO(mvstanton): if the map isn't callable then we have an allocation
        // site, and it may make sense to add the Array JSFunction constant.
        if (new_target.has_value()) {
          // Construct; feedback is new_target, which often is also the callee.
2108
          new_target = new_target->Copy(zone());
2109 2110
          new_target->AddConstant(target->object(), zone(), broker());
          callee.AddConstant(target->object(), zone(), broker());
2111
        } else {
2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124
          // Call; target is feedback cell or callee.
          if (target->IsFeedbackCell() &&
              target->AsFeedbackCell().value().IsFeedbackVector()) {
            FeedbackVectorRef vector =
                target->AsFeedbackCell().value().AsFeedbackVector();
            vector.Serialize();
            VirtualClosure virtual_closure(
                vector.shared_function_info().object(), vector.object(),
                Hints());
            callee.AddVirtualClosure(virtual_closure, zone(), broker());
          } else {
            callee.AddConstant(target->object(), zone(), broker());
          }
2125
        }
2126
      }
2127 2128 2129
    }
  }

2130
  Hints result_hints_from_new_target;
2131
  if (new_target.has_value()) {
2132
    ProcessNewTargetForConstruct(*new_target, &result_hints_from_new_target);
2133 2134 2135
    // These hints are a good guess at the resulting object, so they are useful
    // for both the accumulator and the constructor call's receiver. The latter
    // is still missing completely in {arguments} so add it now.
2136
    arguments->insert(arguments->begin(), result_hints_from_new_target);
2137 2138
  }

2139
  // For JSNativeContextSpecialization::InferReceiverRootMap
2140
  Hints new_accumulator_hints = result_hints_from_new_target.Copy(zone());
2141

2142
  ProcessCallOrConstructRecursive(callee, new_target, *arguments,
2143 2144 2145
                                  speculation_mode, padding,
                                  &new_accumulator_hints);
  environment()->accumulator_hints() = new_accumulator_hints;
2146
}
2147

2148
void SerializerForBackgroundCompilation::ProcessCallOrConstructRecursive(
2149
    Hints const& callee, base::Optional<Hints> new_target,
2150 2151
    const HintsVector& arguments, SpeculationMode speculation_mode,
    MissingArgumentsPolicy padding, Hints* result_hints) {
2152
  // For JSCallReducer::ReduceJSCall and JSCallReducer::ReduceJSConstruct.
2153 2154
  for (auto constant : callee.constants()) {
    ProcessCalleeForCallOrConstruct(constant, new_target, arguments,
2155
                                    speculation_mode, padding, result_hints);
2156 2157
  }

2158
  // For JSCallReducer::ReduceJSCall and JSCallReducer::ReduceJSConstruct.
2159
  for (auto hint : callee.virtual_closures()) {
2160
    ProcessCalleeForCallOrConstruct(Callee(hint), new_target, arguments,
2161
                                    speculation_mode, padding, result_hints);
2162
  }
2163 2164 2165 2166 2167

  for (auto hint : callee.virtual_bound_functions()) {
    HintsVector new_arguments = hint.bound_arguments;
    new_arguments.insert(new_arguments.end(), arguments.begin(),
                         arguments.end());
2168 2169 2170
    ProcessCallOrConstructRecursive(hint.bound_target, new_target,
                                    new_arguments, speculation_mode, padding,
                                    result_hints);
2171 2172 2173 2174
  }
}

void SerializerForBackgroundCompilation::ProcessNewTargetForConstruct(
2175
    Hints const& new_target_hints, Hints* result_hints) {
2176 2177
  for (Handle<Object> target : new_target_hints.constants()) {
    if (target->IsJSBoundFunction()) {
2178
      // Unroll the bound function.
2179 2180 2181 2182 2183 2184 2185 2186 2187 2188
      while (target->IsJSBoundFunction()) {
        target = handle(
            Handle<JSBoundFunction>::cast(target)->bound_target_function(),
            broker()->isolate());
      }
    }
    if (target->IsJSFunction()) {
      Handle<JSFunction> new_target(Handle<JSFunction>::cast(target));
      if (new_target->has_prototype_slot(broker()->isolate()) &&
          new_target->has_initial_map()) {
2189
        result_hints->AddMap(
2190 2191
            handle(new_target->initial_map(), broker()->isolate()), zone(),
            broker());
2192 2193 2194 2195 2196 2197
      }
    }
  }

  for (auto const& virtual_bound_function :
       new_target_hints.virtual_bound_functions()) {
2198 2199
    ProcessNewTargetForConstruct(virtual_bound_function.bound_target,
                                 result_hints);
2200
  }
2201 2202 2203
}

void SerializerForBackgroundCompilation::ProcessCallVarArgs(
2204 2205
    ConvertReceiverMode receiver_mode, Hints const& callee,
    interpreter::Register first_reg, int reg_count, FeedbackSlot slot,
2206
    MissingArgumentsPolicy padding) {
2207
  HintsVector args = PrepareArgumentsHints(first_reg, reg_count);
2208 2209 2210
  // The receiver is either given in the first register or it is implicitly
  // the {undefined} value.
  if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
2211 2212 2213
    args.insert(args.begin(),
                Hints::SingleConstant(
                    broker()->isolate()->factory()->undefined_value(), zone()));
2214
  }
2215
  ProcessCallOrConstruct(callee, base::nullopt, &args, slot, padding);
2216 2217
}

2218 2219
void SerializerForBackgroundCompilation::ProcessApiCall(
    Handle<SharedFunctionInfo> target, const HintsVector& arguments) {
2220 2221 2222 2223 2224 2225 2226 2227 2228 2229
  ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
                          Builtins::kCallFunctionTemplate_CheckAccess));
  ObjectRef(broker(),
            broker()->isolate()->builtins()->builtin_handle(
                Builtins::kCallFunctionTemplate_CheckCompatibleReceiver));
  ObjectRef(
      broker(),
      broker()->isolate()->builtins()->builtin_handle(
          Builtins::kCallFunctionTemplate_CheckAccessAndCompatibleReceiver));

2230 2231 2232
  FunctionTemplateInfoRef target_template_info(
      broker(), handle(target->function_data(), broker()->isolate()));
  if (!target_template_info.has_call_code()) return;
2233 2234
  target_template_info.SerializeCallCode();

2235 2236 2237 2238
  SharedFunctionInfoRef target_ref(broker(), target);
  target_ref.SerializeFunctionTemplateInfo();

  if (target_template_info.accept_any_receiver() &&
2239
      target_template_info.is_signature_undefined()) {
2240
    return;
2241
  }
2242

2243
  if (arguments.empty()) return;
2244 2245 2246 2247 2248
  Hints const& receiver_hints = arguments[0];
  for (auto hint : receiver_hints.constants()) {
    if (hint->IsUndefined()) {
      // The receiver is the global proxy.
      Handle<JSGlobalProxy> global_proxy =
2249
          broker()->target_native_context().global_proxy_object().object();
2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268
      ProcessReceiverMapForApiCall(
          target_template_info,
          handle(global_proxy->map(), broker()->isolate()));
      continue;
    }

    if (!hint->IsJSReceiver()) continue;
    Handle<JSReceiver> receiver(Handle<JSReceiver>::cast(hint));

    ProcessReceiverMapForApiCall(target_template_info,
                                 handle(receiver->map(), broker()->isolate()));
  }

  for (auto receiver_map : receiver_hints.maps()) {
    ProcessReceiverMapForApiCall(target_template_info, receiver_map);
  }
}

void SerializerForBackgroundCompilation::ProcessReceiverMapForApiCall(
2269
    FunctionTemplateInfoRef target, Handle<Map> receiver) {
2270 2271
  if (!receiver->is_access_check_needed()) {
    MapRef receiver_map(broker(), receiver);
2272
    TRACE_BROKER(broker(), "Serializing holder for target: " << target);
2273 2274
    target.LookupHolderOfExpectedType(receiver_map,
                                      SerializationPolicy::kSerializeIfNeeded);
2275 2276 2277
  }
}

2278 2279 2280 2281 2282 2283 2284 2285
void SerializerForBackgroundCompilation::ProcessHintsForObjectCreate(
    Hints const& prototype) {
  for (Handle<Object> constant_handle : prototype.constants()) {
    ObjectRef constant(broker(), constant_handle);
    if (constant.IsJSObject()) constant.AsJSObject().SerializeObjectCreateMap();
  }
}

2286
void SerializerForBackgroundCompilation::ProcessBuiltinCall(
2287 2288
    Handle<SharedFunctionInfo> target, base::Optional<Hints> new_target,
    const HintsVector& arguments, SpeculationMode speculation_mode,
2289
    MissingArgumentsPolicy padding, Hints* result_hints) {
2290
  DCHECK(target->HasBuiltinId());
2291
  const int builtin_id = target->builtin_id();
2292 2293
  const char* name = Builtins::name(builtin_id);
  TRACE_BROKER(broker(), "Serializing for call to builtin " << name);
2294
  switch (builtin_id) {
2295 2296 2297 2298 2299
    case Builtins::kObjectCreate: {
      if (arguments.size() >= 2) {
        ProcessHintsForObjectCreate(arguments[1]);
      } else {
        ProcessHintsForObjectCreate(Hints::SingleConstant(
2300
            broker()->isolate()->factory()->undefined_value(), zone()));
2301 2302 2303
      }
      break;
    }
2304 2305
    case Builtins::kPromisePrototypeCatch: {
      // For JSCallReducer::ReducePromisePrototypeCatch.
2306
      if (speculation_mode != SpeculationMode::kDisallowSpeculation) {
2307 2308 2309
        if (arguments.size() >= 1) {
          ProcessMapHintsForPromises(arguments[0]);
        }
2310
      }
2311 2312
      break;
    }
2313
    case Builtins::kPromisePrototypeFinally: {
2314
      // For JSCallReducer::ReducePromisePrototypeFinally.
2315
      if (speculation_mode != SpeculationMode::kDisallowSpeculation) {
2316 2317 2318
        if (arguments.size() >= 1) {
          ProcessMapHintsForPromises(arguments[0]);
        }
2319 2320 2321 2322 2323 2324
        SharedFunctionInfoRef(
            broker(),
            broker()->isolate()->factory()->promise_catch_finally_shared_fun());
        SharedFunctionInfoRef(
            broker(),
            broker()->isolate()->factory()->promise_then_finally_shared_fun());
2325
      }
2326
      break;
2327 2328
    }
    case Builtins::kPromisePrototypeThen: {
2329
      // For JSCallReducer::ReducePromisePrototypeThen.
2330
      if (speculation_mode != SpeculationMode::kDisallowSpeculation) {
2331 2332 2333
        if (arguments.size() >= 1) {
          ProcessMapHintsForPromises(arguments[0]);
        }
2334
      }
2335 2336
      break;
    }
2337 2338 2339
    case Builtins::kPromiseResolveTrampoline:
      // For JSCallReducer::ReducePromiseInternalResolve and
      // JSNativeContextSpecialization::ReduceJSResolvePromise.
2340
      if (arguments.size() >= 1) {
2341
        Hints const resolution_hints =
2342 2343 2344
            arguments.size() >= 2
                ? arguments[1]
                : Hints::SingleConstant(
2345 2346
                      broker()->isolate()->factory()->undefined_value(),
                      zone());
2347 2348 2349
        ProcessHintsForPromiseResolve(resolution_hints);
      }
      break;
2350
    case Builtins::kRegExpPrototypeTest:
2351
    case Builtins::kRegExpPrototypeTestFast:
2352
      // For JSCallReducer::ReduceRegExpPrototypeTest.
2353 2354
      if (arguments.size() >= 1 &&
          speculation_mode != SpeculationMode::kDisallowSpeculation) {
2355 2356 2357 2358
        Hints const& regexp_hints = arguments[0];
        ProcessHintsForRegExpTest(regexp_hints);
      }
      break;
2359 2360 2361 2362 2363 2364
    case Builtins::kArrayEvery:
    case Builtins::kArrayFilter:
    case Builtins::kArrayForEach:
    case Builtins::kArrayPrototypeFind:
    case Builtins::kArrayPrototypeFindIndex:
    case Builtins::kArrayMap:
2365 2366 2367 2368 2369 2370 2371 2372 2373
    case Builtins::kArraySome:
      if (arguments.size() >= 2 &&
          speculation_mode != SpeculationMode::kDisallowSpeculation) {
        Hints const& callback = arguments[1];
        // "Call(callbackfn, T, « kValue, k, O »)"
        HintsVector new_arguments(zone());
        new_arguments.push_back(
            arguments.size() < 3
                ? Hints::SingleConstant(
2374
                      broker()->isolate()->factory()->undefined_value(), zone())
2375 2376 2377 2378 2379
                : arguments[2]);                // T
        new_arguments.push_back(Hints());       // kValue
        new_arguments.push_back(Hints());       // k
        new_arguments.push_back(arguments[0]);  // O
        for (auto constant : callback.constants()) {
2380 2381 2382
          ProcessCalleeForCallOrConstruct(
              constant, base::nullopt, new_arguments, speculation_mode,
              kMissingArgumentsAreUndefined, result_hints);
2383
        }
2384
        for (auto virtual_closure : callback.virtual_closures()) {
2385
          ProcessCalleeForCallOrConstruct(
2386 2387
              Callee(virtual_closure), base::nullopt, new_arguments,
              speculation_mode, kMissingArgumentsAreUndefined, result_hints);
2388
        }
2389 2390
      }
      break;
2391 2392 2393
    case Builtins::kArrayReduce:
    case Builtins::kArrayReduceRight:
      if (arguments.size() >= 2 &&
2394
          speculation_mode != SpeculationMode::kDisallowSpeculation) {
2395
        Hints const& callback = arguments[1];
2396 2397 2398
        // "Call(callbackfn, undefined, « accumulator, kValue, k, O »)"
        HintsVector new_arguments(zone());
        new_arguments.push_back(Hints::SingleConstant(
2399
            broker()->isolate()->factory()->undefined_value(), zone()));
2400 2401 2402 2403
        new_arguments.push_back(Hints());       // accumulator
        new_arguments.push_back(Hints());       // kValue
        new_arguments.push_back(Hints());       // k
        new_arguments.push_back(arguments[0]);  // O
2404
        for (auto constant : callback.constants()) {
2405 2406 2407
          ProcessCalleeForCallOrConstruct(
              constant, base::nullopt, new_arguments, speculation_mode,
              kMissingArgumentsAreUndefined, result_hints);
2408
        }
2409
        for (auto virtual_closure : callback.virtual_closures()) {
2410
          ProcessCalleeForCallOrConstruct(
2411 2412
              Callee(virtual_closure), base::nullopt, new_arguments,
              speculation_mode, kMissingArgumentsAreUndefined, result_hints);
2413
        }
2414 2415 2416
      }
      break;
    case Builtins::kFunctionPrototypeApply:
2417 2418
      if (arguments.size() >= 1) {
        // Drop hints for all arguments except the user-given receiver.
2419
        Hints const new_receiver =
2420 2421 2422
            arguments.size() >= 2
                ? arguments[1]
                : Hints::SingleConstant(
2423 2424
                      broker()->isolate()->factory()->undefined_value(),
                      zone());
2425 2426
        HintsVector new_arguments({new_receiver}, zone());
        for (auto constant : arguments[0].constants()) {
2427 2428 2429
          ProcessCalleeForCallOrConstruct(
              constant, base::nullopt, new_arguments, speculation_mode,
              kMissingArgumentsAreUnknown, result_hints);
2430
        }
2431 2432 2433 2434 2435
        for (auto const& virtual_closure : arguments[0].virtual_closures()) {
          ProcessCalleeForCallOrConstruct(
              Callee(virtual_closure), base::nullopt, new_arguments,
              speculation_mode, kMissingArgumentsAreUnknown, result_hints);
        }
2436 2437
      }
      break;
2438 2439
    case Builtins::kPromiseConstructor:
      if (arguments.size() >= 1) {
2440 2441 2442 2443
        // "Call(executor, undefined, « resolvingFunctions.[[Resolve]],
        //                              resolvingFunctions.[[Reject]] »)"
        HintsVector new_arguments(
            {Hints::SingleConstant(
2444
                broker()->isolate()->factory()->undefined_value(), zone())},
2445
            zone());
2446
        for (auto constant : arguments[0].constants()) {
2447 2448 2449 2450
          ProcessCalleeForCallOrConstruct(
              constant, base::nullopt, new_arguments,
              SpeculationMode::kDisallowSpeculation,
              kMissingArgumentsAreUnknown, result_hints);
2451
        }
2452
        for (auto const& virtual_closure : arguments[0].virtual_closures()) {
2453
          ProcessCalleeForCallOrConstruct(
2454
              Callee(virtual_closure), base::nullopt, new_arguments,
2455 2456
              SpeculationMode::kDisallowSpeculation,
              kMissingArgumentsAreUnknown, result_hints);
2457
        }
2458
      }
2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469
      SharedFunctionInfoRef(
          broker(), broker()
                        ->isolate()
                        ->factory()
                        ->promise_capability_default_reject_shared_fun());
      SharedFunctionInfoRef(
          broker(), broker()
                        ->isolate()
                        ->factory()
                        ->promise_capability_default_resolve_shared_fun());

2470 2471 2472 2473 2474 2475
      break;
    case Builtins::kFunctionPrototypeCall:
      if (arguments.size() >= 1) {
        HintsVector new_arguments(arguments.begin() + 1, arguments.end(),
                                  zone());
        for (auto constant : arguments[0].constants()) {
2476 2477
          ProcessCalleeForCallOrConstruct(constant, base::nullopt,
                                          new_arguments, speculation_mode,
2478
                                          padding, result_hints);
2479
        }
2480 2481 2482 2483 2484
        for (auto const& virtual_closure : arguments[0].virtual_closures()) {
          ProcessCalleeForCallOrConstruct(
              Callee(virtual_closure), base::nullopt, new_arguments,
              speculation_mode, padding, result_hints);
        }
2485 2486 2487 2488 2489
      }
      break;
    case Builtins::kReflectApply:
    case Builtins::kReflectConstruct:
      if (arguments.size() >= 2) {
2490
        for (auto constant : arguments[1].constants()) {
2491
          if (constant->IsJSFunction()) {
2492
            JSFunctionRef(broker(), constant).Serialize();
2493
          }
2494
        }
2495 2496
      }
      break;
2497 2498
    case Builtins::kObjectPrototypeIsPrototypeOf:
      if (arguments.size() >= 2) {
2499 2500 2501 2502 2503 2504 2505
        ProcessHintsForHasInPrototypeChain(arguments[1]);
      }
      break;
    case Builtins::kFunctionPrototypeHasInstance:
      // For JSCallReducer::ReduceFunctionPrototypeHasInstance.
      if (arguments.size() >= 2) {
        ProcessHintsForOrdinaryHasInstance(arguments[0], arguments[1]);
2506 2507
      }
      break;
2508
    case Builtins::kFastFunctionPrototypeBind:
2509
      if (arguments.size() >= 1 &&
2510
          speculation_mode != SpeculationMode::kDisallowSpeculation) {
2511 2512 2513 2514
        Hints const& bound_target = arguments[0];
        ProcessHintsForFunctionBind(bound_target);
        HintsVector new_arguments(arguments.begin() + 1, arguments.end(),
                                  zone());
2515
        result_hints->AddVirtualBoundFunction(
2516 2517
            VirtualBoundFunction(bound_target, new_arguments), zone(),
            broker());
2518 2519
      }
      break;
2520 2521 2522 2523 2524
    case Builtins::kObjectGetPrototypeOf:
    case Builtins::kReflectGetPrototypeOf:
      if (arguments.size() >= 2) {
        ProcessHintsForObjectGetPrototype(arguments[1]);
      } else {
2525
        Hints const undefined_hint = Hints::SingleConstant(
2526
            broker()->isolate()->factory()->undefined_value(), zone());
2527 2528 2529 2530 2531 2532 2533 2534
        ProcessHintsForObjectGetPrototype(undefined_hint);
      }
      break;
    case Builtins::kObjectPrototypeGetProto:
      if (arguments.size() >= 1) {
        ProcessHintsForObjectGetPrototype(arguments[0]);
      }
      break;
2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546
    case Builtins::kMapIteratorPrototypeNext:
      ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
                              Builtins::kOrderedHashTableHealIndex));
      ObjectRef(broker(),
                broker()->isolate()->factory()->empty_ordered_hash_map());
      break;
    case Builtins::kSetIteratorPrototypeNext:
      ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(
                              Builtins::kOrderedHashTableHealIndex));
      ObjectRef(broker(),
                broker()->isolate()->factory()->empty_ordered_hash_set());
      break;
2547 2548 2549 2550 2551
    default:
      break;
  }
}

2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567
void SerializerForBackgroundCompilation::ProcessHintsForOrdinaryHasInstance(
    Hints const& constructor_hints, Hints const& instance_hints) {
  bool walk_prototypes = false;
  for (Handle<Object> constructor : constructor_hints.constants()) {
    // For JSNativeContextSpecialization::ReduceJSOrdinaryHasInstance.
    if (constructor->IsHeapObject()) {
      ProcessConstantForOrdinaryHasInstance(
          HeapObjectRef(broker(), constructor), &walk_prototypes);
    }
  }
  // For JSNativeContextSpecialization::ReduceJSHasInPrototypeChain.
  if (walk_prototypes) ProcessHintsForHasInPrototypeChain(instance_hints);
}

void SerializerForBackgroundCompilation::ProcessHintsForHasInPrototypeChain(
    Hints const& instance_hints) {
2568 2569 2570 2571 2572 2573 2574 2575
  auto processMap = [&](Handle<Map> map_handle) {
    MapRef map(broker(), map_handle);
    while (map.IsJSObjectMap()) {
      map.SerializePrototype();
      map = map.prototype().map();
    }
  };

2576
  for (auto hint : instance_hints.constants()) {
2577 2578 2579 2580
    if (!hint->IsHeapObject()) continue;
    Handle<HeapObject> object(Handle<HeapObject>::cast(hint));
    processMap(handle(object->map(), broker()->isolate()));
  }
2581
  for (auto map_hint : instance_hints.maps()) {
2582 2583 2584 2585
    processMap(map_hint);
  }
}

2586 2587 2588
void SerializerForBackgroundCompilation::ProcessHintsForPromiseResolve(
    Hints const& resolution_hints) {
  auto processMap = [&](Handle<Map> map) {
2589 2590 2591 2592 2593
    broker()->GetPropertyAccessInfo(
        MapRef(broker(), map),
        NameRef(broker(), broker()->isolate()->factory()->then_string()),
        AccessMode::kLoad, dependencies(),
        SerializationPolicy::kSerializeIfNeeded);
2594 2595 2596
  };

  for (auto hint : resolution_hints.constants()) {
2597 2598 2599
    if (!hint->IsHeapObject()) continue;
    Handle<HeapObject> resolution(Handle<HeapObject>::cast(hint));
    processMap(handle(resolution->map(), broker()->isolate()));
2600 2601 2602 2603 2604 2605
  }
  for (auto map_hint : resolution_hints.maps()) {
    processMap(map_hint);
  }
}

2606 2607 2608
void SerializerForBackgroundCompilation::ProcessMapHintsForPromises(
    Hints const& receiver_hints) {
  // We need to serialize the prototypes on each receiver map.
2609 2610 2611 2612 2613
  for (auto constant : receiver_hints.constants()) {
    if (!constant->IsJSPromise()) continue;
    Handle<Map> map(Handle<HeapObject>::cast(constant)->map(),
                    broker()->isolate());
    MapRef(broker(), map).SerializePrototype();
2614
  }
2615 2616 2617
  for (auto map : receiver_hints.maps()) {
    if (!map->IsJSPromiseMap()) continue;
    MapRef(broker(), map).SerializePrototype();
2618 2619 2620
  }
}

2621 2622
PropertyAccessInfo SerializerForBackgroundCompilation::ProcessMapForRegExpTest(
    MapRef map) {
2623 2624 2625 2626
  PropertyAccessInfo ai_exec = broker()->GetPropertyAccessInfo(
      map, NameRef(broker(), broker()->isolate()->factory()->exec_string()),
      AccessMode::kLoad, dependencies(),
      SerializationPolicy::kSerializeIfNeeded);
2627 2628 2629 2630 2631

  Handle<JSObject> holder;
  if (ai_exec.IsDataConstant() && ai_exec.holder().ToHandle(&holder)) {
    // The property is on the prototype chain.
    JSObjectRef holder_ref(broker(), holder);
2632
    holder_ref.GetOwnDataProperty(ai_exec.field_representation(),
2633 2634
                                  ai_exec.field_index(),
                                  SerializationPolicy::kSerializeIfNeeded);
2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650
  }
  return ai_exec;
}

void SerializerForBackgroundCompilation::ProcessHintsForRegExpTest(
    Hints const& regexp_hints) {
  for (auto hint : regexp_hints.constants()) {
    if (!hint->IsJSRegExp()) continue;
    Handle<JSRegExp> regexp(Handle<JSRegExp>::cast(hint));
    Handle<Map> regexp_map(regexp->map(), broker()->isolate());
    PropertyAccessInfo ai_exec =
        ProcessMapForRegExpTest(MapRef(broker(), regexp_map));
    Handle<JSObject> holder;
    if (ai_exec.IsDataConstant() && !ai_exec.holder().ToHandle(&holder)) {
      // The property is on the object itself.
      JSObjectRef holder_ref(broker(), regexp);
2651
      holder_ref.GetOwnDataProperty(ai_exec.field_representation(),
2652 2653
                                    ai_exec.field_index(),
                                    SerializationPolicy::kSerializeIfNeeded);
2654 2655 2656 2657 2658 2659 2660 2661 2662
    }
  }

  for (auto map : regexp_hints.maps()) {
    if (!map->IsJSRegExpMap()) continue;
    ProcessMapForRegExpTest(MapRef(broker(), map));
  }
}

2663 2664 2665 2666 2667 2668 2669
namespace {
void ProcessMapForFunctionBind(MapRef map) {
  map.SerializePrototype();
  int min_nof_descriptors = i::Max(JSFunction::kLengthDescriptorIndex,
                                   JSFunction::kNameDescriptorIndex) +
                            1;
  if (map.NumberOfOwnDescriptors() >= min_nof_descriptors) {
2670 2671 2672
    map.SerializeOwnDescriptor(
        InternalIndex(JSFunction::kLengthDescriptorIndex));
    map.SerializeOwnDescriptor(InternalIndex(JSFunction::kNameDescriptorIndex));
2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692
  }
}
}  // namespace

void SerializerForBackgroundCompilation::ProcessHintsForFunctionBind(
    Hints const& receiver_hints) {
  for (auto constant : receiver_hints.constants()) {
    if (!constant->IsJSFunction()) continue;
    JSFunctionRef function(broker(), constant);
    function.Serialize();
    ProcessMapForFunctionBind(function.map());
  }

  for (auto map : receiver_hints.maps()) {
    if (!map->IsJSFunctionMap()) continue;
    MapRef map_ref(broker(), map);
    ProcessMapForFunctionBind(map_ref);
  }
}

2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706
void SerializerForBackgroundCompilation::ProcessHintsForObjectGetPrototype(
    Hints const& object_hints) {
  for (auto constant : object_hints.constants()) {
    if (!constant->IsHeapObject()) continue;
    HeapObjectRef object(broker(), constant);
    object.map().SerializePrototype();
  }

  for (auto map : object_hints.maps()) {
    MapRef map_ref(broker(), map);
    map_ref.SerializePrototype();
  }
}

2707 2708 2709 2710 2711
void SerializerForBackgroundCompilation::ContributeToJumpTargetEnvironment(
    int target_offset) {
  auto it = jump_target_environments_.find(target_offset);
  if (it == jump_target_environments_.end()) {
    jump_target_environments_[target_offset] =
2712
        zone()->New<Environment>(*environment());
2713
  } else {
2714
    it->second->Merge(environment(), zone(), broker());
2715 2716
  }
}
2717

2718 2719 2720 2721
void SerializerForBackgroundCompilation::IncorporateJumpTargetEnvironment(
    int target_offset) {
  auto it = jump_target_environments_.find(target_offset);
  if (it != jump_target_environments_.end()) {
2722
    environment()->Merge(it->second, zone(), broker());
2723 2724
    jump_target_environments_.erase(it);
  }
2725 2726
}

2727
void SerializerForBackgroundCompilation::ProcessJump(
2728
    interpreter::BytecodeArrayIterator* iterator) {
2729 2730 2731
  int jump_target = iterator->GetJumpTargetOffset();
  if (iterator->current_offset() < jump_target) {
    ContributeToJumpTargetEnvironment(jump_target);
2732 2733 2734
  }
}

2735
void SerializerForBackgroundCompilation::VisitReturn(
2736
    BytecodeArrayIterator* iterator) {
2737 2738
  return_value_hints().Add(environment()->accumulator_hints(), zone(),
                           broker());
2739
  environment()->Kill();
2740 2741
}

2742 2743 2744 2745 2746
void SerializerForBackgroundCompilation::VisitSwitchOnSmiNoFeedback(
    interpreter::BytecodeArrayIterator* iterator) {
  interpreter::JumpTableTargetOffsets targets =
      iterator->GetJumpTableTargetOffsets();
  for (const auto& target : targets) {
2747
    ContributeToJumpTargetEnvironment(target.target_offset);
2748 2749 2750
  }
}

2751 2752
void SerializerForBackgroundCompilation::VisitSwitchOnGeneratorState(
    interpreter::BytecodeArrayIterator* iterator) {
2753
  for (const auto& target : GetBytecodeAnalysis().resume_jump_targets()) {
2754 2755 2756 2757
    ContributeToJumpTargetEnvironment(target.target_offset());
  }
}

2758
void SerializerForBackgroundCompilation::VisitConstruct(
2759
    BytecodeArrayIterator* iterator) {
2760
  Hints& new_target = environment()->accumulator_hints();
2761
  Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
2762
  interpreter::Register first_reg = iterator->GetRegisterOperand(1);
2763
  size_t reg_count = iterator->GetRegisterCountOperand(2);
2764
  FeedbackSlot slot = iterator->GetSlotOperand(3);
2765

2766
  HintsVector args = PrepareArgumentsHints(first_reg, reg_count);
2767

2768
  ProcessCallOrConstruct(callee, new_target, &args, slot,
2769
                         kMissingArgumentsAreUndefined);
2770 2771
}

2772
void SerializerForBackgroundCompilation::VisitConstructWithSpread(
2773
    BytecodeArrayIterator* iterator) {
2774
  Hints const& new_target = environment()->accumulator_hints();
2775
  Hints const& callee = register_hints(iterator->GetRegisterOperand(0));
2776
  interpreter::Register first_reg = iterator->GetRegisterOperand(1);
2777
  size_t reg_count = iterator->GetRegisterCountOperand(2);
2778
  FeedbackSlot slot = iterator->GetSlotOperand(3);
2779

2780 2781
  DCHECK_GT(reg_count, 0);
  reg_count--;  // Pop the spread element.
2782
  HintsVector args = PrepareArgumentsHints(first_reg, reg_count);
2783

2784
  ProcessCallOrConstruct(callee, new_target, &args, slot,
2785
                         kMissingArgumentsAreUnknown);
2786 2787
}

2788 2789 2790 2791 2792 2793
void SerializerForBackgroundCompilation::ProcessGlobalAccess(FeedbackSlot slot,
                                                             bool is_load) {
  if (slot.IsInvalid() || feedback_vector().is_null()) return;
  FeedbackSource source(feedback_vector(), slot);
  ProcessedFeedback const& feedback =
      broker()->ProcessFeedbackForGlobalAccess(source);
2794

2795
  if (is_load) {
2796
    Hints result_hints;
2797 2798 2799 2800 2801
    if (feedback.kind() == ProcessedFeedback::kGlobalAccess) {
      // We may be able to contribute to accumulator constant hints.
      base::Optional<ObjectRef> value =
          feedback.AsGlobalAccess().GetConstantHint();
      if (value.has_value()) {
2802
        result_hints.AddConstant(value->object(), zone(), broker());
2803 2804 2805 2806
      }
    } else {
      DCHECK(feedback.IsInsufficient());
    }
2807
    environment()->accumulator_hints() = result_hints;
2808 2809 2810 2811 2812
  }
}

void SerializerForBackgroundCompilation::VisitLdaGlobal(
    BytecodeArrayIterator* iterator) {
2813 2814
  NameRef(broker(),
          iterator->GetConstantForIndexOperand(0, broker()->isolate()));
2815 2816
  FeedbackSlot slot = iterator->GetSlotOperand(1);
  ProcessGlobalAccess(slot, true);
2817 2818 2819 2820 2821 2822 2823
}

void SerializerForBackgroundCompilation::VisitLdaGlobalInsideTypeof(
    BytecodeArrayIterator* iterator) {
  VisitLdaGlobal(iterator);
}

2824 2825 2826 2827
void SerializerForBackgroundCompilation::VisitLdaLookupSlot(
    BytecodeArrayIterator* iterator) {
  ObjectRef(broker(),
            iterator->GetConstantForIndexOperand(0, broker()->isolate()));
2828
  environment()->accumulator_hints() = Hints();
2829 2830 2831 2832 2833 2834
}

void SerializerForBackgroundCompilation::VisitLdaLookupSlotInsideTypeof(
    BytecodeArrayIterator* iterator) {
  ObjectRef(broker(),
            iterator->GetConstantForIndexOperand(0, broker()->isolate()));
2835
  environment()->accumulator_hints() = Hints();
2836 2837
}

2838 2839 2840
void SerializerForBackgroundCompilation::ProcessCheckContextExtensions(
    int depth) {
  // for BytecodeGraphBuilder::CheckContextExtensions.
2841
  Hints const& context_hints = environment()->current_context_hints();
2842 2843 2844 2845
  for (int i = 0; i < depth; i++) {
    ProcessContextAccess(context_hints, Context::EXTENSION_INDEX, i,
                         kSerializeSlot);
  }
2846
  SharedFunctionInfoRef shared(broker(), function().shared());
2847
  shared.SerializeScopeInfoChain();
2848 2849 2850
}

void SerializerForBackgroundCompilation::ProcessLdaLookupGlobalSlot(
2851
    BytecodeArrayIterator* iterator) {
2852 2853
  ProcessCheckContextExtensions(iterator->GetUnsignedImmediateOperand(2));
  // TODO(neis): BytecodeGraphBilder may insert a JSLoadGlobal.
2854 2855 2856
  VisitLdaGlobal(iterator);
}

2857 2858 2859 2860 2861
void SerializerForBackgroundCompilation::VisitLdaLookupGlobalSlot(
    BytecodeArrayIterator* iterator) {
  ProcessLdaLookupGlobalSlot(iterator);
}

2862 2863
void SerializerForBackgroundCompilation::VisitLdaLookupGlobalSlotInsideTypeof(
    BytecodeArrayIterator* iterator) {
2864
  ProcessLdaLookupGlobalSlot(iterator);
2865 2866 2867 2868
}

void SerializerForBackgroundCompilation::VisitStaGlobal(
    BytecodeArrayIterator* iterator) {
2869 2870
  NameRef(broker(),
          iterator->GetConstantForIndexOperand(0, broker()->isolate()));
2871
  FeedbackSlot slot = iterator->GetSlotOperand(1);
2872
  ProcessGlobalAccess(slot, false);
2873 2874
}

2875 2876 2877 2878
void SerializerForBackgroundCompilation::ProcessLdaLookupContextSlot(
    BytecodeArrayIterator* iterator) {
  const int slot_index = iterator->GetIndexOperand(1);
  const int depth = iterator->GetUnsignedImmediateOperand(2);
2879 2880
  NameRef(broker(),
          iterator->GetConstantForIndexOperand(0, broker()->isolate()));
2881
  ProcessCheckContextExtensions(depth);
2882
  environment()->accumulator_hints() = Hints();
2883 2884
  ProcessContextAccess(environment()->current_context_hints(), slot_index,
                       depth, kIgnoreSlot);
2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896
}

void SerializerForBackgroundCompilation::VisitLdaLookupContextSlot(
    BytecodeArrayIterator* iterator) {
  ProcessLdaLookupContextSlot(iterator);
}

void SerializerForBackgroundCompilation::VisitLdaLookupContextSlotInsideTypeof(
    BytecodeArrayIterator* iterator) {
  ProcessLdaLookupContextSlot(iterator);
}

2897
// TODO(neis): Avoid duplicating this.
2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912
namespace {
template <class MapContainer>
MapHandles GetRelevantReceiverMaps(Isolate* isolate, MapContainer const& maps) {
  MapHandles result;
  for (Handle<Map> map : maps) {
    if (Map::TryUpdate(isolate, map).ToHandle(&map) &&
        !map->is_abandoned_prototype_map()) {
      DCHECK(!map->is_deprecated());
      result.push_back(map);
    }
  }
  return result;
}
}  // namespace

2913 2914 2915
void SerializerForBackgroundCompilation::ProcessCompareOperation(
    FeedbackSlot slot) {
  if (slot.IsInvalid() || feedback_vector().is_null()) return;
2916
  FeedbackSource source(function().feedback_vector(), slot);
2917 2918 2919
  ProcessedFeedback const& feedback =
      broker()->ProcessFeedbackForCompareOperation(source);
  if (BailoutOnUninitialized(feedback)) return;
2920
  environment()->accumulator_hints() = Hints();
2921 2922
}

2923 2924 2925 2926 2927
void SerializerForBackgroundCompilation::ProcessForIn(FeedbackSlot slot) {
  if (slot.IsInvalid() || feedback_vector().is_null()) return;
  FeedbackSource source(feedback_vector(), slot);
  ProcessedFeedback const& feedback = broker()->ProcessFeedbackForForIn(source);
  if (BailoutOnUninitialized(feedback)) return;
2928
  environment()->accumulator_hints() = Hints();
2929 2930
}

2931 2932 2933 2934 2935 2936 2937 2938
void SerializerForBackgroundCompilation::ProcessUnaryOrBinaryOperation(
    FeedbackSlot slot, bool honor_bailout_on_uninitialized) {
  if (slot.IsInvalid() || feedback_vector().is_null()) return;
  FeedbackSource source(feedback_vector(), slot);
  // Internally V8 uses binary op feedback also for unary ops.
  ProcessedFeedback const& feedback =
      broker()->ProcessFeedbackForBinaryOperation(source);
  if (honor_bailout_on_uninitialized && BailoutOnUninitialized(feedback)) {
2939 2940
    return;
  }
2941
  environment()->accumulator_hints() = Hints();
2942 2943
}

2944 2945
PropertyAccessInfo
SerializerForBackgroundCompilation::ProcessMapForNamedPropertyAccess(
2946 2947 2948
    Hints* receiver, MapRef receiver_map, NameRef const& name,
    AccessMode access_mode, base::Optional<JSObjectRef> concrete_receiver,
    Hints* result_hints) {
2949 2950 2951
  // For JSNativeContextSpecialization::InferReceiverRootMap
  receiver_map.SerializeRootMap();

2952
  // For JSNativeContextSpecialization::ReduceNamedAccess.
2953 2954
  JSGlobalProxyRef global_proxy =
      broker()->target_native_context().global_proxy_object();
2955 2956
  JSGlobalObjectRef global_object =
      broker()->target_native_context().global_object();
2957
  if (receiver_map.equals(global_proxy.map())) {
2958
    base::Optional<PropertyCellRef> cell = global_object.GetPropertyCell(
2959
        name, SerializationPolicy::kSerializeIfNeeded);
2960
    if (access_mode == AccessMode::kLoad && cell.has_value()) {
2961
      result_hints->AddConstant(cell->value().object(), zone(), broker());
2962
    }
2963
  }
2964

2965
  PropertyAccessInfo access_info = broker()->GetPropertyAccessInfo(
2966 2967
      receiver_map, name, access_mode, dependencies(),
      SerializationPolicy::kSerializeIfNeeded);
2968 2969 2970 2971 2972

  // For JSNativeContextSpecialization::InlinePropertySetterCall
  // and InlinePropertyGetterCall.
  if (access_info.IsAccessorConstant() && !access_info.constant().is_null()) {
    if (access_info.constant()->IsJSFunction()) {
2973 2974
      JSFunctionRef function(broker(), access_info.constant());

2975
      // For JSCallReducer and JSInlining(Heuristic).
2976 2977
      HintsVector arguments({Hints::SingleMap(receiver_map.object(), zone())},
                            zone());
2978 2979 2980 2981 2982 2983 2984
      // In the case of a setter any added result hints won't make sense, but
      // they will be ignored anyways by Process*PropertyAccess due to the
      // access mode not being kLoad.
      ProcessCalleeForCallOrConstruct(
          function.object(), base::nullopt, arguments,
          SpeculationMode::kDisallowSpeculation, kMissingArgumentsAreUndefined,
          result_hints);
2985

2986
      // For JSCallReducer::ReduceCallApiFunction.
2987
      Handle<SharedFunctionInfo> sfi = function.shared().object();
2988 2989 2990
      if (sfi->IsApiFunction()) {
        FunctionTemplateInfoRef fti_ref(
            broker(), handle(sfi->get_api_func_data(), broker()->isolate()));
2991 2992 2993 2994
        if (fti_ref.has_call_code()) {
          fti_ref.SerializeCallCode();
          ProcessReceiverMapForApiCall(fti_ref, receiver_map.object());
        }
2995
      }
2996 2997 2998 2999 3000
    } else if (access_info.constant()->IsJSBoundFunction()) {
      JSBoundFunctionRef function(broker(), access_info.constant());

      // For JSCallReducer::ReduceJSCall.
      function.Serialize();
3001
    } else {
3002 3003
      FunctionTemplateInfoRef fti(broker(), access_info.constant());
      if (fti.has_call_code()) fti.SerializeCallCode();
3004
    }
3005 3006 3007 3008
  } else if (access_info.IsModuleExport()) {
    // For JSNativeContextSpecialization::BuildPropertyLoad
    DCHECK(!access_info.constant().is_null());
    CellRef(broker(), access_info.constant());
3009 3010
  }

3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023
  switch (access_mode) {
    case AccessMode::kLoad:
      // For PropertyAccessBuilder::TryBuildLoadConstantDataField
      if (access_info.IsDataConstant()) {
        base::Optional<JSObjectRef> holder;
        Handle<JSObject> prototype;
        if (access_info.holder().ToHandle(&prototype)) {
          holder = JSObjectRef(broker(), prototype);
        } else {
          CHECK_IMPLIES(concrete_receiver.has_value(),
                        concrete_receiver->map().equals(receiver_map));
          holder = concrete_receiver;
        }
3024

3025 3026 3027 3028 3029
        if (holder.has_value()) {
          base::Optional<ObjectRef> constant(holder->GetOwnDataProperty(
              access_info.field_representation(), access_info.field_index(),
              SerializationPolicy::kSerializeIfNeeded));
          if (constant.has_value()) {
3030
            result_hints->AddConstant(constant->object(), zone(), broker());
3031
          }
3032 3033
        }
      }
3034 3035 3036 3037 3038 3039 3040 3041 3042 3043
      break;
    case AccessMode::kStore:
    case AccessMode::kStoreInLiteral:
      // For MapInference (StoreField case).
      if (access_info.IsDataField() || access_info.IsDataConstant()) {
        Handle<Map> transition_map;
        if (access_info.transition_map().ToHandle(&transition_map)) {
          MapRef map_ref(broker(), transition_map);
          TRACE_BROKER(broker(), "Propagating transition map "
                                     << map_ref << " to receiver hints.");
3044
          receiver->AddMap(transition_map, zone(), broker_, false);
3045 3046 3047 3048 3049
        }
      }
      break;
    case AccessMode::kHas:
      break;
3050 3051 3052
  }

  return access_info;
3053 3054
}

3055 3056
void SerializerForBackgroundCompilation::VisitLdaKeyedProperty(
    BytecodeArrayIterator* iterator) {
3057
  Hints const& key = environment()->accumulator_hints();
3058
  Hints* receiver = &register_hints(iterator->GetRegisterOperand(0));
3059
  FeedbackSlot slot = iterator->GetSlotOperand(1);
3060 3061 3062 3063
  ProcessKeyedPropertyAccess(receiver, key, slot, AccessMode::kLoad, true);
}

void SerializerForBackgroundCompilation::ProcessKeyedPropertyAccess(
3064
    Hints* receiver, Hints const& key, FeedbackSlot slot,
3065 3066 3067 3068 3069 3070 3071 3072 3073 3074
    AccessMode access_mode, bool honor_bailout_on_uninitialized) {
  if (slot.IsInvalid() || feedback_vector().is_null()) return;
  FeedbackSource source(feedback_vector(), slot);
  ProcessedFeedback const& feedback =
      broker()->ProcessFeedbackForPropertyAccess(source, access_mode,
                                                 base::nullopt);
  if (honor_bailout_on_uninitialized && BailoutOnUninitialized(feedback)) {
    return;
  }

3075
  Hints new_accumulator_hints;
3076 3077
  switch (feedback.kind()) {
    case ProcessedFeedback::kElementAccess:
3078
      ProcessElementAccess(*receiver, key, feedback.AsElementAccess(),
3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091
                           access_mode);
      break;
    case ProcessedFeedback::kNamedAccess:
      ProcessNamedAccess(receiver, feedback.AsNamedAccess(), access_mode,
                         &new_accumulator_hints);
      break;
    case ProcessedFeedback::kInsufficient:
      break;
    default:
      UNREACHABLE();
  }

  if (access_mode == AccessMode::kLoad) {
3092
    environment()->accumulator_hints() = new_accumulator_hints;
3093
  }
3094 3095
}

3096
void SerializerForBackgroundCompilation::ProcessNamedPropertyAccess(
3097
    Hints* receiver, NameRef const& name, FeedbackSlot slot,
3098 3099 3100 3101 3102 3103 3104
    AccessMode access_mode) {
  if (slot.IsInvalid() || feedback_vector().is_null()) return;
  FeedbackSource source(feedback_vector(), slot);
  ProcessedFeedback const& feedback =
      broker()->ProcessFeedbackForPropertyAccess(source, access_mode, name);
  if (BailoutOnUninitialized(feedback)) return;

3105
  Hints new_accumulator_hints;
3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118
  switch (feedback.kind()) {
    case ProcessedFeedback::kNamedAccess:
      DCHECK(name.equals(feedback.AsNamedAccess().name()));
      ProcessNamedAccess(receiver, feedback.AsNamedAccess(), access_mode,
                         &new_accumulator_hints);
      break;
    case ProcessedFeedback::kInsufficient:
      break;
    default:
      UNREACHABLE();
  }

  if (access_mode == AccessMode::kLoad) {
3119
    environment()->accumulator_hints() = new_accumulator_hints;
3120 3121 3122 3123
  }
}

void SerializerForBackgroundCompilation::ProcessNamedAccess(
3124 3125
    Hints* receiver, NamedAccessFeedback const& feedback,
    AccessMode access_mode, Hints* result_hints) {
3126
  for (Handle<Map> map : feedback.maps()) {
3127
    MapRef map_ref(broker(), map);
3128 3129
    TRACE_BROKER(broker(), "Propagating feedback map "
                               << map_ref << " to receiver hints.");
3130
    receiver->AddMap(map, zone(), broker_, false);
3131 3132 3133
  }

  for (Handle<Map> map :
3134
       GetRelevantReceiverMaps(broker()->isolate(), receiver->maps())) {
3135
    MapRef map_ref(broker(), map);
3136 3137
    ProcessMapForNamedPropertyAccess(receiver, map_ref, feedback.name(),
                                     access_mode, base::nullopt, result_hints);
3138
  }
3139

3140
  for (Handle<Object> hint : receiver->constants()) {
3141
    ObjectRef object(broker(), hint);
3142
    if (access_mode == AccessMode::kLoad && object.IsJSObject()) {
3143
      MapRef map_ref = object.AsJSObject().map();
3144 3145 3146
      ProcessMapForNamedPropertyAccess(receiver, map_ref, feedback.name(),
                                       access_mode, object.AsJSObject(),
                                       result_hints);
3147
    }
3148
    // For JSNativeContextSpecialization::ReduceJSLoadNamed.
3149 3150
    if (access_mode == AccessMode::kLoad && object.IsJSFunction() &&
        feedback.name().equals(ObjectRef(
3151
            broker(), broker()->isolate()->factory()->prototype_string()))) {
3152 3153
      JSFunctionRef function = object.AsJSFunction();
      function.Serialize();
3154
      if (result_hints != nullptr && function.has_prototype()) {
3155 3156
        result_hints->AddConstant(function.prototype().object(), zone(),
                                  broker());
3157
      }
3158
    }
3159 3160
    // TODO(neis): Also record accumulator hint for string.length and maybe
    // more?
3161
  }
3162
}
3163

3164
void SerializerForBackgroundCompilation::ProcessElementAccess(
3165 3166
    Hints const& receiver, Hints const& key,
    ElementAccessFeedback const& feedback, AccessMode access_mode) {
3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183
  for (auto const& group : feedback.transition_groups()) {
    for (Handle<Map> map_handle : group) {
      MapRef map(broker(), map_handle);
      switch (access_mode) {
        case AccessMode::kHas:
        case AccessMode::kLoad:
          map.SerializeForElementLoad();
          break;
        case AccessMode::kStore:
          map.SerializeForElementStore();
          break;
        case AccessMode::kStoreInLiteral:
          // This operation is fairly local and simple, nothing to serialize.
          break;
      }
    }
  }
3184

3185 3186
  for (Handle<Object> hint : receiver.constants()) {
    ObjectRef receiver_ref(broker(), hint);
3187

3188 3189 3190 3191 3192
    // For JSNativeContextSpecialization::InferReceiverRootMap
    if (receiver_ref.IsHeapObject()) {
      receiver_ref.AsHeapObject().map().SerializeRootMap();
    }

3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216
    // For JSNativeContextSpecialization::ReduceElementAccess.
    if (receiver_ref.IsJSTypedArray()) {
      receiver_ref.AsJSTypedArray().Serialize();
    }

    // For JSNativeContextSpecialization::ReduceElementLoadFromHeapConstant.
    if (access_mode == AccessMode::kLoad || access_mode == AccessMode::kHas) {
      for (Handle<Object> hint : key.constants()) {
        ObjectRef key_ref(broker(), hint);
        // TODO(neis): Do this for integer-HeapNumbers too?
        if (key_ref.IsSmi() && key_ref.AsSmi() >= 0) {
          base::Optional<ObjectRef> element =
              receiver_ref.GetOwnConstantElement(
                  key_ref.AsSmi(), SerializationPolicy::kSerializeIfNeeded);
          if (!element.has_value() && receiver_ref.IsJSArray()) {
            // We didn't find a constant element, but if the receiver is a
            // cow-array we can exploit the fact that any future write to the
            // element will replace the whole elements storage.
            receiver_ref.AsJSArray().GetOwnCowElement(
                key_ref.AsSmi(), SerializationPolicy::kSerializeIfNeeded);
          }
        }
      }
    }
3217
  }
3218 3219 3220 3221 3222 3223

  // For JSNativeContextSpecialization::InferReceiverRootMap
  for (Handle<Map> map : receiver.maps()) {
    MapRef map_ref(broker(), map);
    map_ref.SerializeRootMap();
  }
3224 3225
}

3226 3227
void SerializerForBackgroundCompilation::VisitLdaNamedProperty(
    BytecodeArrayIterator* iterator) {
3228
  Hints* receiver = &register_hints(iterator->GetRegisterOperand(0));
3229 3230
  NameRef name(broker(),
               iterator->GetConstantForIndexOperand(1, broker()->isolate()));
3231
  FeedbackSlot slot = iterator->GetSlotOperand(2);
3232
  ProcessNamedPropertyAccess(receiver, name, slot, AccessMode::kLoad);
3233 3234
}

3235 3236
// TODO(neis): Do feedback-independent serialization also for *NoFeedback
// bytecodes.
3237 3238 3239 3240 3241 3242
void SerializerForBackgroundCompilation::VisitLdaNamedPropertyNoFeedback(
    BytecodeArrayIterator* iterator) {
  NameRef(broker(),
          iterator->GetConstantForIndexOperand(1, broker()->isolate()));
}

3243 3244
void SerializerForBackgroundCompilation::VisitStaNamedProperty(
    BytecodeArrayIterator* iterator) {
3245
  Hints* receiver = &register_hints(iterator->GetRegisterOperand(0));
3246 3247 3248 3249
  NameRef name(broker(),
               iterator->GetConstantForIndexOperand(1, broker()->isolate()));
  FeedbackSlot slot = iterator->GetSlotOperand(2);
  ProcessNamedPropertyAccess(receiver, name, slot, AccessMode::kStore);
3250 3251
}

3252 3253 3254 3255 3256 3257
void SerializerForBackgroundCompilation::VisitStaNamedPropertyNoFeedback(
    BytecodeArrayIterator* iterator) {
  NameRef(broker(),
          iterator->GetConstantForIndexOperand(1, broker()->isolate()));
}

3258 3259
void SerializerForBackgroundCompilation::VisitStaNamedOwnProperty(
    BytecodeArrayIterator* iterator) {
3260
  Hints* receiver = &register_hints(iterator->GetRegisterOperand(0));
3261 3262 3263 3264
  NameRef name(broker(),
               iterator->GetConstantForIndexOperand(1, broker()->isolate()));
  FeedbackSlot slot = iterator->GetSlotOperand(2);
  ProcessNamedPropertyAccess(receiver, name, slot, AccessMode::kStoreInLiteral);
3265 3266
}

3267 3268
void SerializerForBackgroundCompilation::VisitTestIn(
    BytecodeArrayIterator* iterator) {
3269
  Hints* receiver = &environment()->accumulator_hints();
3270
  Hints const& key = register_hints(iterator->GetRegisterOperand(0));
3271
  FeedbackSlot slot = iterator->GetSlotOperand(1);
3272
  ProcessKeyedPropertyAccess(receiver, key, slot, AccessMode::kHas, false);
3273 3274
}

3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297
// For JSNativeContextSpecialization::ReduceJSOrdinaryHasInstance.
void SerializerForBackgroundCompilation::ProcessConstantForOrdinaryHasInstance(
    HeapObjectRef const& constructor, bool* walk_prototypes) {
  if (constructor.IsJSBoundFunction()) {
    constructor.AsJSBoundFunction().Serialize();
    ProcessConstantForInstanceOf(
        constructor.AsJSBoundFunction().bound_target_function(),
        walk_prototypes);
  } else if (constructor.IsJSFunction()) {
    constructor.AsJSFunction().Serialize();
    *walk_prototypes =
        *walk_prototypes ||
        (constructor.map().has_prototype_slot() &&
         constructor.AsJSFunction().has_prototype() &&
         !constructor.AsJSFunction().PrototypeRequiresRuntimeLookup());
  }
}

void SerializerForBackgroundCompilation::ProcessConstantForInstanceOf(
    ObjectRef const& constructor, bool* walk_prototypes) {
  if (!constructor.IsHeapObject()) return;
  HeapObjectRef constructor_heap_object = constructor.AsHeapObject();

3298 3299 3300 3301 3302
  PropertyAccessInfo access_info = broker()->GetPropertyAccessInfo(
      constructor_heap_object.map(),
      NameRef(broker(), broker()->isolate()->factory()->has_instance_symbol()),
      AccessMode::kLoad, dependencies(),
      SerializationPolicy::kSerializeIfNeeded);
3303 3304 3305 3306 3307 3308 3309 3310 3311 3312

  if (access_info.IsNotFound()) {
    ProcessConstantForOrdinaryHasInstance(constructor_heap_object,
                                          walk_prototypes);
  } else if (access_info.IsDataConstant()) {
    Handle<JSObject> holder;
    bool found_on_proto = access_info.holder().ToHandle(&holder);
    JSObjectRef holder_ref = found_on_proto ? JSObjectRef(broker(), holder)
                                            : constructor.AsJSObject();
    base::Optional<ObjectRef> constant = holder_ref.GetOwnDataProperty(
3313 3314
        access_info.field_representation(), access_info.field_index(),
        SerializationPolicy::kSerializeIfNeeded);
3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329
    CHECK(constant.has_value());
    if (constant->IsJSFunction()) {
      JSFunctionRef function = constant->AsJSFunction();
      function.Serialize();
      if (function.shared().HasBuiltinId() &&
          function.shared().builtin_id() ==
              Builtins::kFunctionPrototypeHasInstance) {
        // For JSCallReducer::ReduceFunctionPrototypeHasInstance.
        ProcessConstantForOrdinaryHasInstance(constructor_heap_object,
                                              walk_prototypes);
      }
    }
  }
}

3330 3331
void SerializerForBackgroundCompilation::VisitTestInstanceOf(
    BytecodeArrayIterator* iterator) {
3332
  Hints const& lhs = register_hints(iterator->GetRegisterOperand(0));
3333
  Hints rhs = environment()->accumulator_hints();
3334
  FeedbackSlot slot = iterator->GetSlotOperand(1);
3335 3336 3337 3338 3339 3340 3341

  if (slot.IsInvalid() || feedback_vector().is_null()) return;
  FeedbackSource source(feedback_vector(), slot);
  ProcessedFeedback const& feedback =
      broker()->ProcessFeedbackForInstanceOf(source);

  // Incorporate feedback (about rhs) into hints copy to simplify processing.
3342
  // TODO(neis): Propagate into original hints?
3343 3344 3345
  if (!feedback.IsInsufficient()) {
    InstanceOfFeedback const& rhs_feedback = feedback.AsInstanceOf();
    if (rhs_feedback.value().has_value()) {
3346
      rhs = rhs.Copy(zone());
3347
      Handle<JSObject> constructor = rhs_feedback.value()->object();
3348
      rhs.AddConstant(constructor, zone(), broker());
3349 3350 3351
    }
  }

3352 3353 3354 3355 3356 3357
  bool walk_prototypes = false;
  for (Handle<Object> constant : rhs.constants()) {
    ProcessConstantForInstanceOf(ObjectRef(broker(), constant),
                                 &walk_prototypes);
  }
  if (walk_prototypes) ProcessHintsForHasInPrototypeChain(lhs);
3358

3359
  environment()->accumulator_hints() = Hints();
3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371
}

void SerializerForBackgroundCompilation::VisitToNumeric(
    BytecodeArrayIterator* iterator) {
  FeedbackSlot slot = iterator->GetSlotOperand(0);
  ProcessUnaryOrBinaryOperation(slot, false);
}

void SerializerForBackgroundCompilation::VisitToNumber(
    BytecodeArrayIterator* iterator) {
  FeedbackSlot slot = iterator->GetSlotOperand(0);
  ProcessUnaryOrBinaryOperation(slot, false);
3372 3373
}

3374 3375 3376 3377 3378 3379
void SerializerForBackgroundCompilation::VisitThrowReferenceErrorIfHole(
    BytecodeArrayIterator* iterator) {
  ObjectRef(broker(),
            iterator->GetConstantForIndexOperand(0, broker()->isolate()));
}

3380 3381
void SerializerForBackgroundCompilation::VisitStaKeyedProperty(
    BytecodeArrayIterator* iterator) {
3382 3383
  Hints* receiver = &register_hints(iterator->GetRegisterOperand(0));
  Hints const& key = register_hints(iterator->GetRegisterOperand(1));
3384
  FeedbackSlot slot = iterator->GetSlotOperand(2);
3385
  ProcessKeyedPropertyAccess(receiver, key, slot, AccessMode::kStore, true);
3386 3387 3388 3389
}

void SerializerForBackgroundCompilation::VisitStaInArrayLiteral(
    BytecodeArrayIterator* iterator) {
3390 3391
  Hints* receiver = &register_hints(iterator->GetRegisterOperand(0));
  Hints const& key = register_hints(iterator->GetRegisterOperand(1));
3392
  FeedbackSlot slot = iterator->GetSlotOperand(2);
3393 3394
  ProcessKeyedPropertyAccess(receiver, key, slot, AccessMode::kStoreInLiteral,
                             true);
3395 3396
}

3397 3398
void SerializerForBackgroundCompilation::VisitStaDataPropertyInLiteral(
    BytecodeArrayIterator* iterator) {
3399 3400
  Hints* receiver = &register_hints(iterator->GetRegisterOperand(0));
  Hints const& key = register_hints(iterator->GetRegisterOperand(1));
3401 3402 3403 3404 3405
  FeedbackSlot slot = iterator->GetSlotOperand(3);
  ProcessKeyedPropertyAccess(receiver, key, slot, AccessMode::kStoreInLiteral,
                             false);
}

3406 3407
#define DEFINE_CLEAR_ACCUMULATOR(name, ...)             \
  void SerializerForBackgroundCompilation::Visit##name( \
3408
      BytecodeArrayIterator* iterator) {                \
3409
    environment()->accumulator_hints() = Hints();       \
3410 3411 3412
  }
CLEAR_ACCUMULATOR_LIST(DEFINE_CLEAR_ACCUMULATOR)
#undef DEFINE_CLEAR_ACCUMULATOR
3413

3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425
#define DEFINE_CONDITIONAL_JUMP(name, ...)              \
  void SerializerForBackgroundCompilation::Visit##name( \
      BytecodeArrayIterator* iterator) {                \
    ProcessJump(iterator);                              \
  }
CONDITIONAL_JUMPS_LIST(DEFINE_CONDITIONAL_JUMP)
#undef DEFINE_CONDITIONAL_JUMP

#define DEFINE_UNCONDITIONAL_JUMP(name, ...)            \
  void SerializerForBackgroundCompilation::Visit##name( \
      BytecodeArrayIterator* iterator) {                \
    ProcessJump(iterator);                              \
3426
    environment()->Kill();                              \
3427 3428 3429 3430 3431 3432 3433
  }
UNCONDITIONAL_JUMPS_LIST(DEFINE_UNCONDITIONAL_JUMP)
#undef DEFINE_UNCONDITIONAL_JUMP

#define DEFINE_IGNORE(name, ...)                        \
  void SerializerForBackgroundCompilation::Visit##name( \
      BytecodeArrayIterator* iterator) {}
3434
IGNORED_BYTECODE_LIST(DEFINE_IGNORE)
3435 3436
#undef DEFINE_IGNORE

3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452
#define DEFINE_UNREACHABLE(name, ...)                   \
  void SerializerForBackgroundCompilation::Visit##name( \
      BytecodeArrayIterator* iterator) {                \
    UNREACHABLE();                                      \
  }
UNREACHABLE_BYTECODE_LIST(DEFINE_UNREACHABLE)
#undef DEFINE_UNREACHABLE

#define DEFINE_KILL(name, ...)                          \
  void SerializerForBackgroundCompilation::Visit##name( \
      BytecodeArrayIterator* iterator) {                \
    environment()->Kill();                              \
  }
KILL_ENVIRONMENT_LIST(DEFINE_KILL)
#undef DEFINE_KILL

3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480
#define DEFINE_BINARY_OP(name, ...)                     \
  void SerializerForBackgroundCompilation::Visit##name( \
      BytecodeArrayIterator* iterator) {                \
    FeedbackSlot slot = iterator->GetSlotOperand(1);    \
    ProcessUnaryOrBinaryOperation(slot, true);          \
  }
BINARY_OP_LIST(DEFINE_BINARY_OP)
#undef DEFINE_BINARY_OP

#define DEFINE_COMPARE_OP(name, ...)                    \
  void SerializerForBackgroundCompilation::Visit##name( \
      BytecodeArrayIterator* iterator) {                \
    FeedbackSlot slot = iterator->GetSlotOperand(1);    \
    ProcessCompareOperation(slot);                      \
  }
COMPARE_OP_LIST(DEFINE_COMPARE_OP)
#undef DEFINE_COMPARE_OP

#define DEFINE_UNARY_OP(name, ...)                      \
  void SerializerForBackgroundCompilation::Visit##name( \
      BytecodeArrayIterator* iterator) {                \
    FeedbackSlot slot = iterator->GetSlotOperand(0);    \
    ProcessUnaryOrBinaryOperation(slot, true);          \
  }
UNARY_OP_LIST(DEFINE_UNARY_OP)
#undef DEFINE_UNARY_OP

#undef BINARY_OP_LIST
3481
#undef CLEAR_ACCUMULATOR_LIST
3482
#undef COMPARE_OP_LIST
3483 3484
#undef CONDITIONAL_JUMPS_LIST
#undef IGNORED_BYTECODE_LIST
3485
#undef KILL_ENVIRONMENT_LIST
3486
#undef SUPPORTED_BYTECODE_LIST
3487 3488 3489
#undef UNARY_OP_LIST
#undef UNCONDITIONAL_JUMPS_LIST
#undef UNREACHABLE_BYTECODE_LIST
3490

3491 3492 3493
}  // namespace compiler
}  // namespace internal
}  // namespace v8