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#include "src/deoptimizer/translation-array.h" 6 7#include "src/base/vlq.h" 8#include "src/deoptimizer/translated-state.h" 9#include "src/objects/fixed-array-inl.h" 10#include "third_party/zlib/google/compression_utils_portable.h" 11 12namespace v8 { 13namespace internal { 14 15namespace { 16 17// Constants describing compressed TranslationArray layout. Only relevant if 18// --turbo-compress-translation-arrays is enabled. 19constexpr int kUncompressedSizeOffset = 0; 20constexpr int kUncompressedSizeSize = kInt32Size; 21constexpr int kCompressedDataOffset = 22 kUncompressedSizeOffset + kUncompressedSizeSize; 23constexpr int kTranslationArrayElementSize = kInt32Size; 24 25} // namespace 26 27TranslationArrayIterator::TranslationArrayIterator(TranslationArray buffer, 28 int index) 29 : buffer_(buffer), index_(index) { 30 if (V8_UNLIKELY(FLAG_turbo_compress_translation_arrays)) { 31 const int size = buffer_.get_int(kUncompressedSizeOffset); 32 uncompressed_contents_.insert(uncompressed_contents_.begin(), size, 0); 33 34 uLongf uncompressed_size = size * kTranslationArrayElementSize; 35 36 CHECK_EQ( 37 zlib_internal::UncompressHelper( 38 zlib_internal::ZRAW, 39 bit_cast<Bytef*>(uncompressed_contents_.data()), &uncompressed_size, 40 buffer_.GetDataStartAddress() + kCompressedDataOffset, 41 buffer_.DataSize()), 42 Z_OK); 43 DCHECK(index >= 0 && index < size); 44 } else { 45 DCHECK(index >= 0 && index < buffer.length()); 46 } 47} 48 49int32_t TranslationArrayIterator::Next() { 50 if (V8_UNLIKELY(FLAG_turbo_compress_translation_arrays)) { 51 return uncompressed_contents_[index_++]; 52 } else { 53 int32_t value = base::VLQDecode(buffer_.GetDataStartAddress(), &index_); 54 DCHECK_LE(index_, buffer_.length()); 55 return value; 56 } 57} 58 59bool TranslationArrayIterator::HasNext() const { 60 if (V8_UNLIKELY(FLAG_turbo_compress_translation_arrays)) { 61 return index_ < static_cast<int>(uncompressed_contents_.size()); 62 } else { 63 return index_ < buffer_.length(); 64 } 65} 66 67void TranslationArrayBuilder::Add(int32_t value) { 68 if (V8_UNLIKELY(FLAG_turbo_compress_translation_arrays)) { 69 contents_for_compression_.push_back(value); 70 } else { 71 base::VLQEncode(&contents_, value); 72 } 73} 74 75Handle<TranslationArray> TranslationArrayBuilder::ToTranslationArray( 76 Factory* factory) { 77 if (V8_UNLIKELY(FLAG_turbo_compress_translation_arrays)) { 78 const int input_size = SizeInBytes(); 79 uLongf compressed_data_size = compressBound(input_size); 80 81 ZoneVector<byte> compressed_data(compressed_data_size, zone()); 82 83 CHECK_EQ( 84 zlib_internal::CompressHelper( 85 zlib_internal::ZRAW, compressed_data.data(), &compressed_data_size, 86 bit_cast<const Bytef*>(contents_for_compression_.data()), 87 input_size, Z_DEFAULT_COMPRESSION, nullptr, nullptr), 88 Z_OK); 89 90 const int translation_array_size = 91 static_cast<int>(compressed_data_size) + kUncompressedSizeSize; 92 Handle<TranslationArray> result = 93 factory->NewByteArray(translation_array_size, AllocationType::kOld); 94 95 result->set_int(kUncompressedSizeOffset, Size()); 96 std::memcpy(result->GetDataStartAddress() + kCompressedDataOffset, 97 compressed_data.data(), compressed_data_size); 98 99 return result; 100 } else { 101 Handle<TranslationArray> result = 102 factory->NewByteArray(SizeInBytes(), AllocationType::kOld); 103 memcpy(result->GetDataStartAddress(), contents_.data(), 104 contents_.size() * sizeof(uint8_t)); 105 return result; 106 } 107} 108 109void TranslationArrayBuilder::BeginBuiltinContinuationFrame( 110 BytecodeOffset bytecode_offset, int literal_id, unsigned height) { 111 auto opcode = TranslationOpcode::BUILTIN_CONTINUATION_FRAME; 112 Add(opcode); 113 Add(bytecode_offset.ToInt()); 114 Add(literal_id); 115 Add(height); 116 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 3); 117} 118 119#if V8_ENABLE_WEBASSEMBLY 120void TranslationArrayBuilder::BeginJSToWasmBuiltinContinuationFrame( 121 BytecodeOffset bytecode_offset, int literal_id, unsigned height, 122 base::Optional<wasm::ValueKind> return_kind) { 123 auto opcode = TranslationOpcode::JS_TO_WASM_BUILTIN_CONTINUATION_FRAME; 124 Add(opcode); 125 Add(bytecode_offset.ToInt()); 126 Add(literal_id); 127 Add(height); 128 Add(return_kind ? static_cast<int>(return_kind.value()) : kNoWasmReturnKind); 129 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 4); 130} 131#endif // V8_ENABLE_WEBASSEMBLY 132 133void TranslationArrayBuilder::BeginJavaScriptBuiltinContinuationFrame( 134 BytecodeOffset bytecode_offset, int literal_id, unsigned height) { 135 auto opcode = TranslationOpcode::JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME; 136 Add(opcode); 137 Add(bytecode_offset.ToInt()); 138 Add(literal_id); 139 Add(height); 140 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 3); 141} 142 143void TranslationArrayBuilder::BeginJavaScriptBuiltinContinuationWithCatchFrame( 144 BytecodeOffset bytecode_offset, int literal_id, unsigned height) { 145 auto opcode = 146 TranslationOpcode::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME; 147 Add(opcode); 148 Add(bytecode_offset.ToInt()); 149 Add(literal_id); 150 Add(height); 151 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 3); 152} 153 154void TranslationArrayBuilder::BeginConstructStubFrame( 155 BytecodeOffset bytecode_offset, int literal_id, unsigned height) { 156 auto opcode = TranslationOpcode::CONSTRUCT_STUB_FRAME; 157 Add(opcode); 158 Add(bytecode_offset.ToInt()); 159 Add(literal_id); 160 Add(height); 161 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 3); 162} 163 164void TranslationArrayBuilder::BeginArgumentsAdaptorFrame(int literal_id, 165 unsigned height) { 166 auto opcode = TranslationOpcode::ARGUMENTS_ADAPTOR_FRAME; 167 Add(opcode); 168 Add(literal_id); 169 Add(height); 170 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 2); 171} 172 173void TranslationArrayBuilder::BeginInterpretedFrame( 174 BytecodeOffset bytecode_offset, int literal_id, unsigned height, 175 int return_value_offset, int return_value_count) { 176 auto opcode = TranslationOpcode::INTERPRETED_FRAME; 177 Add(opcode); 178 Add(bytecode_offset.ToInt()); 179 Add(literal_id); 180 Add(height); 181 Add(return_value_offset); 182 Add(return_value_count); 183 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 5); 184} 185 186void TranslationArrayBuilder::ArgumentsElements(CreateArgumentsType type) { 187 auto opcode = TranslationOpcode::ARGUMENTS_ELEMENTS; 188 Add(opcode); 189 Add(static_cast<uint8_t>(type)); 190 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1); 191} 192 193void TranslationArrayBuilder::ArgumentsLength() { 194 auto opcode = TranslationOpcode::ARGUMENTS_LENGTH; 195 Add(opcode); 196 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 0); 197} 198 199void TranslationArrayBuilder::BeginCapturedObject(int length) { 200 auto opcode = TranslationOpcode::CAPTURED_OBJECT; 201 Add(opcode); 202 Add(length); 203 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1); 204} 205 206void TranslationArrayBuilder::DuplicateObject(int object_index) { 207 auto opcode = TranslationOpcode::DUPLICATED_OBJECT; 208 Add(opcode); 209 Add(object_index); 210 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1); 211} 212 213void TranslationArrayBuilder::StoreRegister(Register reg) { 214 auto opcode = TranslationOpcode::REGISTER; 215 Add(opcode); 216 Add(reg.code()); 217} 218 219void TranslationArrayBuilder::StoreInt32Register(Register reg) { 220 auto opcode = TranslationOpcode::INT32_REGISTER; 221 Add(opcode); 222 Add(reg.code()); 223 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1); 224} 225 226void TranslationArrayBuilder::StoreInt64Register(Register reg) { 227 auto opcode = TranslationOpcode::INT64_REGISTER; 228 Add(opcode); 229 Add(reg.code()); 230 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1); 231} 232 233void TranslationArrayBuilder::StoreUint32Register(Register reg) { 234 auto opcode = TranslationOpcode::UINT32_REGISTER; 235 Add(opcode); 236 Add(reg.code()); 237} 238 239void TranslationArrayBuilder::StoreBoolRegister(Register reg) { 240 auto opcode = TranslationOpcode::BOOL_REGISTER; 241 Add(opcode); 242 Add(reg.code()); 243 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1); 244} 245 246void TranslationArrayBuilder::StoreFloatRegister(FloatRegister reg) { 247 auto opcode = TranslationOpcode::FLOAT_REGISTER; 248 Add(opcode); 249 Add(reg.code()); 250} 251 252void TranslationArrayBuilder::StoreDoubleRegister(DoubleRegister reg) { 253 auto opcode = TranslationOpcode::DOUBLE_REGISTER; 254 Add(opcode); 255 Add(reg.code()); 256 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1); 257} 258 259void TranslationArrayBuilder::StoreStackSlot(int index) { 260 auto opcode = TranslationOpcode::STACK_SLOT; 261 Add(opcode); 262 Add(index); 263 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1); 264} 265 266void TranslationArrayBuilder::StoreInt32StackSlot(int index) { 267 auto opcode = TranslationOpcode::INT32_STACK_SLOT; 268 Add(opcode); 269 Add(index); 270 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1); 271} 272 273void TranslationArrayBuilder::StoreInt64StackSlot(int index) { 274 auto opcode = TranslationOpcode::INT64_STACK_SLOT; 275 Add(opcode); 276 Add(index); 277 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1); 278} 279 280void TranslationArrayBuilder::StoreUint32StackSlot(int index) { 281 auto opcode = TranslationOpcode::UINT32_STACK_SLOT; 282 Add(opcode); 283 Add(index); 284 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1); 285} 286 287void TranslationArrayBuilder::StoreBoolStackSlot(int index) { 288 auto opcode = TranslationOpcode::BOOL_STACK_SLOT; 289 Add(opcode); 290 Add(index); 291 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1); 292} 293 294void TranslationArrayBuilder::StoreFloatStackSlot(int index) { 295 auto opcode = TranslationOpcode::FLOAT_STACK_SLOT; 296 Add(opcode); 297 Add(index); 298 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1); 299} 300 301void TranslationArrayBuilder::StoreDoubleStackSlot(int index) { 302 auto opcode = TranslationOpcode::DOUBLE_STACK_SLOT; 303 Add(opcode); 304 Add(index); 305 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1); 306} 307 308void TranslationArrayBuilder::StoreLiteral(int literal_id) { 309 auto opcode = TranslationOpcode::LITERAL; 310 Add(opcode); 311 Add(literal_id); 312 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1); 313} 314 315void TranslationArrayBuilder::AddUpdateFeedback(int vector_literal, int slot) { 316 auto opcode = TranslationOpcode::UPDATE_FEEDBACK; 317 Add(opcode); 318 Add(vector_literal); 319 Add(slot); 320 DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 2); 321} 322 323void TranslationArrayBuilder::StoreJSFrameFunction() { 324 StoreStackSlot((StandardFrameConstants::kCallerPCOffset - 325 StandardFrameConstants::kFunctionOffset) / 326 kSystemPointerSize); 327} 328 329} // namespace internal 330} // namespace v8 331