builtin-serializer.cc 5.56 KB
Newer Older
1 2 3 4 5 6
// Copyright 2017 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/snapshot/builtin-serializer.h"

7
#include "src/interpreter/interpreter.h"
8 9 10 11 12 13
#include "src/objects-inl.h"
#include "src/snapshot/startup-serializer.h"

namespace v8 {
namespace internal {

14 15 16 17
using interpreter::Bytecode;
using interpreter::Bytecodes;
using interpreter::OperandScale;

18 19 20 21 22 23 24 25
BuiltinSerializer::BuiltinSerializer(Isolate* isolate,
                                     StartupSerializer* startup_serializer)
    : Serializer(isolate), startup_serializer_(startup_serializer) {}

BuiltinSerializer::~BuiltinSerializer() {
  OutputStatistics("BuiltinSerializer");
}

26 27 28 29 30 31 32
void BuiltinSerializer::SerializeBuiltinsAndHandlers() {
  // Serialize builtins.

  STATIC_ASSERT(0 == BSU::kFirstBuiltinIndex);

  for (int i = 0; i < BSU::kNumberOfBuiltins; i++) {
    SetBuiltinOffset(i, sink_.Position());
33
    SerializeBuiltin(isolate()->builtins()->builtin(i));
34
  }
35

36 37 38
#ifdef V8_EMBEDDED_BYTECODE_HANDLERS
  STATIC_ASSERT(BSU::kNumberOfBuiltins == BSU::kNumberOfCodeObjects);
#else
39 40 41 42 43 44
  // Serialize bytecode handlers.

  STATIC_ASSERT(BSU::kNumberOfBuiltins == BSU::kFirstHandlerIndex);

  BSU::ForEachBytecode([=](Bytecode bytecode, OperandScale operand_scale) {
    SetHandlerOffset(bytecode, operand_scale, sink_.Position());
45
    if (!Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) return;
46 47 48 49 50

    SerializeHandler(
        isolate()->interpreter()->GetBytecodeHandler(bytecode, operand_scale));
  });

51 52 53 54 55 56 57 58 59
  STATIC_ASSERT(BSU::kFirstHandlerIndex + BSU::kNumberOfHandlers ==
                BSU::kNumberOfCodeObjects);

  // The DeserializeLazy handlers are serialized by the StartupSerializer
  // during strong root iteration.

  DCHECK(isolate()->heap()->deserialize_lazy_handler()->IsCode());
  DCHECK(isolate()->heap()->deserialize_lazy_handler_wide()->IsCode());
  DCHECK(isolate()->heap()->deserialize_lazy_handler_extra_wide()->IsCode());
60
#endif  // V8_EMBEDDED_BYTECODE_HANDLERS
61

62 63
  // Pad with kNop since GetInt() might read too far.
  Pad();
64 65 66

  // Append the offset table. During deserialization, the offset table is
  // extracted by BuiltinSnapshotData.
67 68
  const byte* data = reinterpret_cast<const byte*>(&code_offsets_[0]);
  int data_length = static_cast<int>(sizeof(code_offsets_));
69
  sink_.PutRaw(data, data_length, "BuiltinOffsets");
70 71
}

72 73
void BuiltinSerializer::VisitRootPointers(Root root, const char* description,
                                          Object** start, Object** end) {
74
  UNREACHABLE();  // We iterate manually in SerializeBuiltins.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
}

void BuiltinSerializer::SerializeBuiltin(Code* code) {
  DCHECK_GE(code->builtin_index(), 0);

  // All builtins are serialized unconditionally when the respective builtin is
  // reached while iterating the builtins list. A builtin seen at any other
  // time (e.g. startup snapshot creation, or while iterating a builtin code
  // object during builtin serialization) is serialized by reference - see
  // BuiltinSerializer::SerializeObject below.
  ObjectSerializer object_serializer(this, code, &sink_, kPlain,
                                     kStartOfObject);
  object_serializer.Serialize();
}

90
void BuiltinSerializer::SerializeHandler(Code* code) {
91
  DCHECK(ObjectIsBytecodeHandler(code));
92 93 94 95 96
  ObjectSerializer object_serializer(this, code, &sink_, kPlain,
                                     kStartOfObject);
  object_serializer.Serialize();
}

97 98 99 100 101
void BuiltinSerializer::SerializeObject(HeapObject* o, HowToCode how_to_code,
                                        WhereToPoint where_to_point, int skip) {
  DCHECK(!o->IsSmi());

  // Roots can simply be serialized as root references.
102
  int root_index = root_index_map()->Lookup(o);
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
  if (root_index != RootIndexMap::kInvalidRootIndex) {
    DCHECK(startup_serializer_->root_has_been_serialized(root_index));
    PutRoot(root_index, o, how_to_code, where_to_point, skip);
    return;
  }

  // Builtins are serialized using a dedicated bytecode. We only reach this
  // point if encountering a Builtin e.g. while iterating the body of another
  // builtin.
  if (SerializeBuiltinReference(o, how_to_code, where_to_point, skip)) return;

  // Embedded objects are serialized as part of the partial snapshot cache.
  // Currently we expect to see:
  // * Code: Jump targets.
  // * ByteArrays: Relocation infos.
  // * FixedArrays: Handler tables.
  // * Strings: CSA_ASSERTs in debug builds, various other string constants.
  // * HeapNumbers: Embedded constants.
  // TODO(6624): Jump targets should never trigger content serialization, it
  // should always result in a reference instead. Reloc infos and handler
  // tables should not end up in the partial snapshot cache.

  FlushSkip(skip);

  int cache_index = startup_serializer_->PartialSnapshotCacheIndex(o);
  sink_.Put(kPartialSnapshotCache + how_to_code + where_to_point,
            "PartialSnapshotCache");
  sink_.PutInt(cache_index, "partial_snapshot_cache_index");
}

133 134 135 136 137 138
void BuiltinSerializer::SetBuiltinOffset(int builtin_id, uint32_t offset) {
  DCHECK(Builtins::IsBuiltinId(builtin_id));
  DCHECK(BSU::IsBuiltinIndex(builtin_id));
  code_offsets_[builtin_id] = offset;
}

139
#ifndef V8_EMBEDDED_BYTECODE_HANDLERS
140 141 142 143 144 145 146
void BuiltinSerializer::SetHandlerOffset(Bytecode bytecode,
                                         OperandScale operand_scale,
                                         uint32_t offset) {
  const int index = BSU::BytecodeToIndex(bytecode, operand_scale);
  DCHECK(BSU::IsHandlerIndex(index));
  code_offsets_[index] = offset;
}
147
#endif  // V8_EMBEDDED_BYTECODE_HANDLERS
148

149 150
}  // namespace internal
}  // namespace v8