// Copyright 2016 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.

#ifndef V8_SNAPSHOT_CODE_SERIALIZER_H_
#define V8_SNAPSHOT_CODE_SERIALIZER_H_

#include "src/parsing/preparse-data.h"
#include "src/snapshot/serializer.h"

namespace v8 {
namespace internal {

class CodeSerializer : public Serializer<> {
 public:
  static ScriptData* Serialize(Isolate* isolate,
                               Handle<SharedFunctionInfo> info,
                               Handle<String> source);

  ScriptData* Serialize(Handle<HeapObject> obj);

  MUST_USE_RESULT static MaybeHandle<SharedFunctionInfo> Deserialize(
      Isolate* isolate, ScriptData* cached_data, Handle<String> source);

  const std::vector<uint32_t>* stub_keys() const { return &stub_keys_; }

  uint32_t source_hash() const { return source_hash_; }

 protected:
  explicit CodeSerializer(Isolate* isolate, uint32_t source_hash)
      : Serializer(isolate), source_hash_(source_hash) {}
  ~CodeSerializer() override { OutputStatistics("CodeSerializer"); }

  virtual void SerializeCodeObject(Code* code_object, HowToCode how_to_code,
                                   WhereToPoint where_to_point) {
    UNREACHABLE();
  }

  virtual bool ElideObject(Object* obj) { return false; }
  void SerializeGeneric(HeapObject* heap_object, HowToCode how_to_code,
                        WhereToPoint where_to_point);

 private:
  void SerializeObject(HeapObject* o, HowToCode how_to_code,
                       WhereToPoint where_to_point, int skip) override;

  void SerializeCodeStub(Code* code_stub, HowToCode how_to_code,
                         WhereToPoint where_to_point);

  DisallowHeapAllocation no_gc_;
  uint32_t source_hash_;
  std::vector<uint32_t> stub_keys_;
  DISALLOW_COPY_AND_ASSIGN(CodeSerializer);
};

class WasmCompiledModuleSerializer : public CodeSerializer {
 public:
  static std::unique_ptr<ScriptData> SerializeWasmModule(
      Isolate* isolate, Handle<FixedArray> compiled_module);
  static MaybeHandle<FixedArray> DeserializeWasmModule(
      Isolate* isolate, ScriptData* data, Vector<const byte> wire_bytes);

 protected:
  void SerializeCodeObject(Code* code_object, HowToCode how_to_code,
                           WhereToPoint where_to_point) override;
  bool ElideObject(Object* obj) override;

 private:
  WasmCompiledModuleSerializer(Isolate* isolate, uint32_t source_hash,
                               Handle<Context> native_context,
                               Handle<SeqOneByteString> module_bytes);
  DISALLOW_COPY_AND_ASSIGN(WasmCompiledModuleSerializer);
};

// Wrapper around ScriptData to provide code-serializer-specific functionality.
class SerializedCodeData : public SerializedData {
 public:
  enum SanityCheckResult {
    CHECK_SUCCESS = 0,
    MAGIC_NUMBER_MISMATCH = 1,
    VERSION_MISMATCH = 2,
    SOURCE_MISMATCH = 3,
    CPU_FEATURES_MISMATCH = 4,
    FLAGS_MISMATCH = 5,
    CHECKSUM_MISMATCH = 6,
    INVALID_HEADER = 7,
    LENGTH_MISMATCH = 8
  };

  // The data header consists of uint32_t-sized entries:
  // [0] magic number and (internally provided) external reference count
  // [1] extra (API-provided) external reference count
  // [2] version hash
  // [3] source hash
  // [4] cpu features
  // [5] flag hash
  // [6] number of code stub keys
  // [7] number of reservation size entries
  // [8] payload length
  // [9] payload checksum part 1
  // [10] payload checksum part 2
  // ...  reservations
  // ...  code stub keys
  // ...  serialized payload
  static const uint32_t kVersionHashOffset = kMagicNumberOffset + kUInt32Size;
  static const uint32_t kSourceHashOffset = kVersionHashOffset + kUInt32Size;
  static const uint32_t kCpuFeaturesOffset = kSourceHashOffset + kUInt32Size;
  static const uint32_t kFlagHashOffset = kCpuFeaturesOffset + kUInt32Size;
  static const uint32_t kNumReservationsOffset = kFlagHashOffset + kUInt32Size;
  static const uint32_t kNumCodeStubKeysOffset =
      kNumReservationsOffset + kUInt32Size;
  static const uint32_t kPayloadLengthOffset =
      kNumCodeStubKeysOffset + kUInt32Size;
  static const uint32_t kChecksum1Offset = kPayloadLengthOffset + kUInt32Size;
  static const uint32_t kChecksum2Offset = kChecksum1Offset + kUInt32Size;
  static const uint32_t kUnalignedHeaderSize = kChecksum2Offset + kUInt32Size;
  static const uint32_t kHeaderSize = POINTER_SIZE_ALIGN(kUnalignedHeaderSize);

  // Used when consuming.
  static SerializedCodeData FromCachedData(Isolate* isolate,
                                           ScriptData* cached_data,
                                           uint32_t expected_source_hash,
                                           SanityCheckResult* rejection_result);

  // Used when producing.
  SerializedCodeData(const std::vector<byte>* payload,
                     const CodeSerializer* cs);

  // Return ScriptData object and relinquish ownership over it to the caller.
  ScriptData* GetScriptData();

  std::vector<Reservation> Reservations() const;
  Vector<const byte> Payload() const;

  Vector<const uint32_t> CodeStubKeys() const;

  static uint32_t SourceHash(Handle<String> source);

 private:
  explicit SerializedCodeData(ScriptData* data);
  SerializedCodeData(const byte* data, int size)
      : SerializedData(const_cast<byte*>(data), size) {}

  Vector<const byte> DataWithoutHeader() const {
    return Vector<const byte>(data_ + kHeaderSize, size_ - kHeaderSize);
  }

  SanityCheckResult SanityCheck(Isolate* isolate,
                                uint32_t expected_source_hash) const;
};

}  // namespace internal
}  // namespace v8

#endif  // V8_SNAPSHOT_CODE_SERIALIZER_H_
