1// Copyright 2021 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_DEOPTIMIZER_TRANSLATION_ARRAY_H_
6#define V8_DEOPTIMIZER_TRANSLATION_ARRAY_H_
7
8#include "src/codegen/register.h"
9#include "src/deoptimizer/translation-opcode.h"
10#include "src/objects/fixed-array.h"
11#include "src/zone/zone-containers.h"
12
13#if V8_ENABLE_WEBASSEMBLY
14#include "src/wasm/value-type.h"
15#endif  // V8_ENABLE_WEBASSEMBLY
16
17namespace v8 {
18namespace internal {
19
20class Factory;
21
22// The TranslationArray is the on-heap representation of translations created
23// during code generation in a (zone-allocated) TranslationArrayBuilder. The
24// translation array specifies how to transform an optimized frame back into
25// one or more unoptimized frames.
26// TODO(jgruber): Consider a real type instead of this type alias.
27using TranslationArray = ByteArray;
28
29class TranslationArrayIterator {
30 public:
31  TranslationArrayIterator(TranslationArray buffer, int index);
32
33  int32_t Next();
34
35  bool HasNext() const;
36
37  void Skip(int n) {
38    for (int i = 0; i < n; i++) Next();
39  }
40
41 private:
42  std::vector<int32_t> uncompressed_contents_;
43  TranslationArray buffer_;
44  int index_;
45};
46
47class TranslationArrayBuilder {
48 public:
49  explicit TranslationArrayBuilder(Zone* zone)
50      : contents_(zone), contents_for_compression_(zone), zone_(zone) {}
51
52  Handle<TranslationArray> ToTranslationArray(Factory* factory);
53
54  int BeginTranslation(int frame_count, int jsframe_count,
55                       int update_feedback_count) {
56    int start_index = Size();
57    auto opcode = TranslationOpcode::BEGIN;
58    Add(opcode);
59    Add(frame_count);
60    Add(jsframe_count);
61    Add(update_feedback_count);
62    DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 3);
63    return start_index;
64  }
65
66  void BeginInterpretedFrame(BytecodeOffset bytecode_offset, int literal_id,
67                             unsigned height, int return_value_offset,
68                             int return_value_count);
69  void BeginArgumentsAdaptorFrame(int literal_id, unsigned height);
70  void BeginConstructStubFrame(BytecodeOffset bailout_id, int literal_id,
71                               unsigned height);
72  void BeginBuiltinContinuationFrame(BytecodeOffset bailout_id, int literal_id,
73                                     unsigned height);
74#if V8_ENABLE_WEBASSEMBLY
75  void BeginJSToWasmBuiltinContinuationFrame(
76      BytecodeOffset bailout_id, int literal_id, unsigned height,
77      base::Optional<wasm::ValueKind> return_kind);
78#endif  // V8_ENABLE_WEBASSEMBLY
79  void BeginJavaScriptBuiltinContinuationFrame(BytecodeOffset bailout_id,
80                                               int literal_id, unsigned height);
81  void BeginJavaScriptBuiltinContinuationWithCatchFrame(
82      BytecodeOffset bailout_id, int literal_id, unsigned height);
83  void ArgumentsElements(CreateArgumentsType type);
84  void ArgumentsLength();
85  void BeginCapturedObject(int length);
86  void AddUpdateFeedback(int vector_literal, int slot);
87  void DuplicateObject(int object_index);
88  void StoreRegister(Register reg);
89  void StoreInt32Register(Register reg);
90  void StoreInt64Register(Register reg);
91  void StoreUint32Register(Register reg);
92  void StoreBoolRegister(Register reg);
93  void StoreFloatRegister(FloatRegister reg);
94  void StoreDoubleRegister(DoubleRegister reg);
95  void StoreStackSlot(int index);
96  void StoreInt32StackSlot(int index);
97  void StoreInt64StackSlot(int index);
98  void StoreUint32StackSlot(int index);
99  void StoreBoolStackSlot(int index);
100  void StoreFloatStackSlot(int index);
101  void StoreDoubleStackSlot(int index);
102  void StoreLiteral(int literal_id);
103  void StoreJSFrameFunction();
104
105 private:
106  void Add(int32_t value);
107  void Add(TranslationOpcode opcode) { Add(static_cast<int32_t>(opcode)); }
108
109  int Size() const {
110    return V8_UNLIKELY(FLAG_turbo_compress_translation_arrays)
111               ? static_cast<int>(contents_for_compression_.size())
112               : static_cast<int>(contents_.size());
113  }
114  int SizeInBytes() const {
115    return V8_UNLIKELY(FLAG_turbo_compress_translation_arrays)
116               ? Size() * kInt32Size
117               : Size();
118  }
119
120  Zone* zone() const { return zone_; }
121
122  ZoneVector<uint8_t> contents_;
123  ZoneVector<int32_t> contents_for_compression_;
124  Zone* const zone_;
125};
126
127}  // namespace internal
128}  // namespace v8
129
130#endif  // V8_DEOPTIMIZER_TRANSLATION_ARRAY_H_
131