blob: b2a6817ae269e7a6475c69e1eddb424cf00f9fe2 [file] [log] [blame]
// Copyright 2021 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_DEOPTIMIZER_FRAME_TRANSLATION_BUILDER_H_
#define V8_DEOPTIMIZER_FRAME_TRANSLATION_BUILDER_H_
#include "src/codegen/register.h"
#include "src/deoptimizer/translation-opcode.h"
#include "src/objects/deoptimization-data.h"
#include "src/zone/zone-containers.h"
#if V8_ENABLE_WEBASSEMBLY
#include "src/wasm/value-type.h"
#endif // V8_ENABLE_WEBASSEMBLY
namespace v8 {
namespace internal {
class LocalFactory;
class FrameTranslationBuilder {
public:
explicit FrameTranslationBuilder(Zone* zone)
: contents_(zone),
contents_for_compression_(zone),
basis_instructions_(zone),
zone_(zone) {}
Handle<DeoptimizationFrameTranslation> ToFrameTranslation(
LocalFactory* factory);
base::Vector<const uint8_t> ToFrameTranslationWasm();
int BeginTranslation(int frame_count, int jsframe_count,
bool update_feedback);
void BeginInterpretedFrame(BytecodeOffset bytecode_offset, int literal_id,
unsigned height, int return_value_offset,
int return_value_count);
void BeginInlinedExtraArguments(int literal_id, unsigned height);
void BeginConstructCreateStubFrame(int literal_id, unsigned height);
void BeginConstructInvokeStubFrame(int literal_id);
void BeginBuiltinContinuationFrame(BytecodeOffset bailout_id, int literal_id,
unsigned height);
#if V8_ENABLE_WEBASSEMBLY
void BeginJSToWasmBuiltinContinuationFrame(
BytecodeOffset bailout_id, int literal_id, unsigned height,
base::Optional<wasm::ValueKind> return_kind);
void BeginWasmInlinedIntoJSFrame(BytecodeOffset bailout_id, int literal_id,
unsigned height);
void BeginLiftoffFrame(BytecodeOffset bailout_id, unsigned height,
uint32_t wasm_function_index);
#endif // V8_ENABLE_WEBASSEMBLY
void BeginJavaScriptBuiltinContinuationFrame(BytecodeOffset bailout_id,
int literal_id, unsigned height);
void BeginJavaScriptBuiltinContinuationWithCatchFrame(
BytecodeOffset bailout_id, int literal_id, unsigned height);
void ArgumentsElements(CreateArgumentsType type);
void ArgumentsLength();
void RestLength();
void BeginCapturedObject(int length);
void AddUpdateFeedback(int vector_literal, int slot);
void DuplicateObject(int object_index);
void StoreRegister(TranslationOpcode opcode, Register reg);
void StoreRegister(Register reg);
void StoreInt32Register(Register reg);
void StoreInt64Register(Register reg);
void StoreSignedBigInt64Register(Register reg);
void StoreUnsignedBigInt64Register(Register reg);
void StoreUint32Register(Register reg);
void StoreBoolRegister(Register reg);
void StoreFloatRegister(FloatRegister reg);
void StoreDoubleRegister(DoubleRegister reg);
void StoreHoleyDoubleRegister(DoubleRegister reg);
void StoreSimd128Register(Simd128Register reg);
void StoreStackSlot(int index);
void StoreInt32StackSlot(int index);
void StoreInt64StackSlot(int index);
void StoreSignedBigInt64StackSlot(int index);
void StoreUnsignedBigInt64StackSlot(int index);
void StoreUint32StackSlot(int index);
void StoreBoolStackSlot(int index);
void StoreFloatStackSlot(int index);
void StoreDoubleStackSlot(int index);
void StoreSimd128StackSlot(int index);
void StoreHoleyDoubleStackSlot(int index);
void StoreLiteral(int literal_id);
void StoreOptimizedOut();
void StoreJSFrameFunction();
private:
struct Instruction {
template <typename... T>
explicit Instruction(TranslationOpcode opcode, T... operands)
: opcode(opcode),
operands{operands.value()...}
#ifdef ENABLE_SLOW_DCHECKS
,
is_operand_signed{operands.IsSigned()...}
#endif
{
}
TranslationOpcode opcode;
// The operands for the instruction. Signed values were static_casted to
// unsigned.
uint32_t operands[kMaxTranslationOperandCount];
#ifdef ENABLE_SLOW_DCHECKS
bool is_operand_signed[kMaxTranslationOperandCount];
#endif
};
// Either adds the instruction or increments matching_instructions_count_,
// depending on whether the instruction matches the corresponding instruction
// from the previous translation.
template <typename... T>
void Add(TranslationOpcode opcode, T... operands);
// Adds the instruction to contents_, without performing the other steps of
// Add(). Requires !v8_flags.turbo_compress_frame_translations.
template <typename... T>
void AddRawToContents(TranslationOpcode opcode, T... operands);
// Adds the instruction to contents_for_compression_, without performing the
// other steps of Add(). Requires v8_flags.turbo_compress_frame_translations.
template <typename... T>
void AddRawToContentsForCompression(TranslationOpcode opcode, T... operands);
// Adds a BEGIN instruction to contents_ or contents_for_compression_, but
// does not update other state. Used by BeginTranslation.
template <typename... T>
void AddRawBegin(bool update_feedback, T... operands);
int Size() const {
return V8_UNLIKELY(v8_flags.turbo_compress_frame_translations)
? static_cast<int>(contents_for_compression_.size())
: static_cast<int>(contents_.size());
}
int SizeInBytes() const {
return V8_UNLIKELY(v8_flags.turbo_compress_frame_translations)
? Size() * kInt32Size
: Size();
}
Zone* zone() const { return zone_; }
void FinishPendingInstructionIfNeeded();
void ValidateBytes(DeoptTranslationIterator& iter) const;
ZoneVector<uint8_t> contents_;
ZoneVector<int32_t> contents_for_compression_;
// If match_previous_allowed_ is false, then this vector contains the
// instructions written so far in the current translation (since the last
// BEGIN). If match_previous_allowed_ is true, then this vector contains the
// instructions from the basis translation (the one written with
// !match_previous_allowed_). This allows Add() to easily check whether a
// newly added instruction matches the corresponding one from the basis
// translation.
ZoneVector<Instruction> basis_instructions_;
#ifdef ENABLE_SLOW_DCHECKS
std::vector<Instruction> all_instructions_;
#endif
Zone* const zone_;
// How many consecutive instructions we've skipped writing because they match
// the basis translation.
size_t matching_instructions_count_ = 0;
size_t total_matching_instructions_in_current_translation_ = 0;
// The current index within basis_instructions_.
size_t instruction_index_within_translation_ = 0;
// The byte index within the contents_ array of the BEGIN instruction for the
// basis translation (the most recent translation which was fully written out,
// not using MATCH_PREVIOUS_TRANSLATION instructions).
int index_of_basis_translation_start_ = 0;
// Whether the builder can use MATCH_PREVIOUS_TRANSLATION in the current
// translation.
bool match_previous_allowed_ = true;
};
} // namespace internal
} // namespace v8
#endif // V8_DEOPTIMIZER_FRAME_TRANSLATION_BUILDER_H_