1bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// Copyright 2015 the V8 project authors. All rights reserved.
2bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// found in the LICENSE file.
4bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
5bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/interpreter/bytecode-array-writer.h"
6bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/api.h"
813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/interpreter/bytecode-label.h"
9f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/interpreter/bytecode-register.h"
1013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/interpreter/constant-array-builder.h"
1113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/log.h"
1262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/objects-inl.h"
13bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
14bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochnamespace v8 {
15bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochnamespace internal {
16bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochnamespace interpreter {
17bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
18f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochSTATIC_CONST_MEMBER_DEFINITION const size_t
19f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    BytecodeArrayWriter::kMaxSizeOfPackedBytecode;
20f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
21bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochBytecodeArrayWriter::BytecodeArrayWriter(
22f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Zone* zone, ConstantArrayBuilder* constant_array_builder,
23f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    SourcePositionTableBuilder::RecordingMode source_position_mode)
24f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    : bytecodes_(zone),
2513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      unbound_jumps_(0),
26f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      source_position_table_builder_(zone, source_position_mode),
27f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      constant_array_builder_(constant_array_builder) {
28f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  bytecodes_.reserve(512);  // Derived via experimentation.
29f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
30bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
31bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// override
32bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochBytecodeArrayWriter::~BytecodeArrayWriter() {}
33bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
34bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// override
3513e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochHandle<BytecodeArray> BytecodeArrayWriter::ToBytecodeArray(
36f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Isolate* isolate, int register_count, int parameter_count,
3713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Handle<FixedArray> handler_table) {
3813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK_EQ(0, unbound_jumps_);
3913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
4013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int bytecode_size = static_cast<int>(bytecodes()->size());
41f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  int frame_size = register_count * kPointerSize;
42f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<FixedArray> constant_pool =
43f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      constant_array_builder()->ToFixedArray(isolate);
44f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<BytecodeArray> bytecode_array = isolate->factory()->NewBytecodeArray(
4513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      bytecode_size, &bytecodes()->front(), frame_size, parameter_count,
4613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      constant_pool);
4713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  bytecode_array->set_handler_table(*handler_table);
48f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<ByteArray> source_position_table =
49f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      source_position_table_builder()->ToSourcePositionTable(
50f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          isolate, Handle<AbstractCode>::cast(bytecode_array));
5113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  bytecode_array->set_source_position_table(*source_position_table);
5213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return bytecode_array;
5313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
54bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
55bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// override
56bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid BytecodeArrayWriter::Write(BytecodeNode* node) {
5713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(!Bytecodes::IsJump(node->bytecode()));
58bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  UpdateSourcePositionTable(node);
59bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  EmitBytecode(node);
60bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
61bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
6213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// override
6313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid BytecodeArrayWriter::WriteJump(BytecodeNode* node, BytecodeLabel* label) {
6413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(Bytecodes::IsJump(node->bytecode()));
6513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  UpdateSourcePositionTable(node);
6613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  EmitJump(node, label);
6713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
6813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
6913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// override
7013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid BytecodeArrayWriter::BindLabel(BytecodeLabel* label) {
7113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  size_t current_offset = bytecodes()->size();
7213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (label->is_forward_target()) {
7313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // An earlier jump instruction refers to this label. Update it's location.
7413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    PatchJump(current_offset, label->offset());
7513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // Now treat as if the label will only be back referred to.
7613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
7713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  label->bind_to(current_offset);
7813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
7913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
8013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// override
8113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid BytecodeArrayWriter::BindLabel(const BytecodeLabel& target,
8213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                    BytecodeLabel* label) {
8313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(!label->is_bound());
8413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(target.is_bound());
8513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (label->is_forward_target()) {
8613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // An earlier jump instruction refers to this label. Update it's location.
8713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    PatchJump(target.offset(), label->offset());
8813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // Now treat as if the label will only be back referred to.
8913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
9013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  label->bind_to(target.offset());
9113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
9213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
93bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid BytecodeArrayWriter::UpdateSourcePositionTable(
94bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    const BytecodeNode* const node) {
95bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  int bytecode_offset = static_cast<int>(bytecodes()->size());
96bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  const BytecodeSourceInfo& source_info = node->source_info();
97bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (source_info.is_valid()) {
98c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    source_position_table_builder()->AddPosition(
99c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        bytecode_offset, SourcePosition(source_info.source_position()),
100c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        source_info.is_statement());
101bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
102bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
103bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
104bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid BytecodeArrayWriter::EmitBytecode(const BytecodeNode* const node) {
105bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK_NE(node->bytecode(), Bytecode::kIllegal);
106bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
107f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Bytecode bytecode = node->bytecode();
108f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  OperandScale operand_scale = node->operand_scale();
109f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
110bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (operand_scale != OperandScale::kSingle) {
111bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Bytecode prefix = Bytecodes::OperandScaleToPrefixBytecode(operand_scale);
112f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    bytecodes()->push_back(Bytecodes::ToByte(prefix));
113bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
114f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  bytecodes()->push_back(Bytecodes::ToByte(bytecode));
115bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
116bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  const uint32_t* const operands = node->operands();
117f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  const int operand_count = node->operand_count();
118f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  const OperandSize* operand_sizes =
119f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      Bytecodes::GetOperandSizes(bytecode, operand_scale);
120f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  for (int i = 0; i < operand_count; ++i) {
121f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    switch (operand_sizes[i]) {
122bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      case OperandSize::kNone:
123bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        UNREACHABLE();
124bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        break;
125bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      case OperandSize::kByte:
126f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        bytecodes()->push_back(static_cast<uint8_t>(operands[i]));
127bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        break;
128bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      case OperandSize::kShort: {
129f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        uint16_t operand = static_cast<uint16_t>(operands[i]);
130f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        const uint8_t* raw_operand = reinterpret_cast<const uint8_t*>(&operand);
131f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        bytecodes()->push_back(raw_operand[0]);
132f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        bytecodes()->push_back(raw_operand[1]);
133bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        break;
134bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      }
135bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      case OperandSize::kQuad: {
136f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        const uint8_t* raw_operand =
137f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch            reinterpret_cast<const uint8_t*>(&operands[i]);
138f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        bytecodes()->push_back(raw_operand[0]);
139f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        bytecodes()->push_back(raw_operand[1]);
140f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        bytecodes()->push_back(raw_operand[2]);
141f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        bytecodes()->push_back(raw_operand[3]);
142bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        break;
143bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      }
144bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
145bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
146bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
147bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
14813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// static
14913e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochBytecode GetJumpWithConstantOperand(Bytecode jump_bytecode) {
15013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  switch (jump_bytecode) {
15113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case Bytecode::kJump:
15213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return Bytecode::kJumpConstant;
15313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case Bytecode::kJumpIfTrue:
15413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return Bytecode::kJumpIfTrueConstant;
15513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case Bytecode::kJumpIfFalse:
15613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return Bytecode::kJumpIfFalseConstant;
15713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case Bytecode::kJumpIfToBooleanTrue:
15813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return Bytecode::kJumpIfToBooleanTrueConstant;
15913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case Bytecode::kJumpIfToBooleanFalse:
16013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return Bytecode::kJumpIfToBooleanFalseConstant;
16113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case Bytecode::kJumpIfNotHole:
16213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return Bytecode::kJumpIfNotHoleConstant;
16313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case Bytecode::kJumpIfNull:
16413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return Bytecode::kJumpIfNullConstant;
16513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case Bytecode::kJumpIfUndefined:
16613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return Bytecode::kJumpIfUndefinedConstant;
16762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case Bytecode::kJumpIfJSReceiver:
16862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      return Bytecode::kJumpIfJSReceiverConstant;
16913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    default:
17013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      UNREACHABLE();
17113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return Bytecode::kIllegal;
17213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
17313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
17413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
17513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid BytecodeArrayWriter::PatchJumpWith8BitOperand(size_t jump_location,
17613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                                   int delta) {
17713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Bytecode jump_bytecode = Bytecodes::FromByte(bytecodes()->at(jump_location));
17862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(Bytecodes::IsForwardJump(jump_bytecode));
17913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode));
18062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(Bytecodes::GetOperandType(jump_bytecode, 0), OperandType::kUImm);
18162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_GT(delta, 0);
18213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  size_t operand_location = jump_location + 1;
18313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK_EQ(bytecodes()->at(operand_location), k8BitJumpPlaceholder);
18462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (Bytecodes::ScaleForUnsignedOperand(delta) == OperandScale::kSingle) {
18562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // The jump fits within the range of an UImm8 operand, so cancel
18613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // the reservation and jump directly.
18713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    constant_array_builder()->DiscardReservedEntry(OperandSize::kByte);
18813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    bytecodes()->at(operand_location) = static_cast<uint8_t>(delta);
18913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else {
19062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // The jump does not fit within the range of an UImm8 operand, so
19113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // commit reservation putting the offset into the constant pool,
19213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // and update the jump instruction and operand.
19313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    size_t entry = constant_array_builder()->CommitReservedEntry(
194f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        OperandSize::kByte, Smi::FromInt(delta));
19513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK_EQ(Bytecodes::SizeForUnsignedOperand(static_cast<uint32_t>(entry)),
19613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch              OperandSize::kByte);
19713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    jump_bytecode = GetJumpWithConstantOperand(jump_bytecode);
19813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    bytecodes()->at(jump_location) = Bytecodes::ToByte(jump_bytecode);
19913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    bytecodes()->at(operand_location) = static_cast<uint8_t>(entry);
20013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
20113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
20213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
20313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid BytecodeArrayWriter::PatchJumpWith16BitOperand(size_t jump_location,
20413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                                    int delta) {
20513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Bytecode jump_bytecode = Bytecodes::FromByte(bytecodes()->at(jump_location));
20662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(Bytecodes::IsForwardJump(jump_bytecode));
20713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode));
20862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(Bytecodes::GetOperandType(jump_bytecode, 0), OperandType::kUImm);
20962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_GT(delta, 0);
21013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  size_t operand_location = jump_location + 1;
21113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint8_t operand_bytes[2];
21262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (Bytecodes::ScaleForUnsignedOperand(delta) <= OperandScale::kDouble) {
213f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // The jump fits within the range of an Imm16 operand, so cancel
214f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // the reservation and jump directly.
21513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    constant_array_builder()->DiscardReservedEntry(OperandSize::kShort);
21613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(delta));
21713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else {
218f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // The jump does not fit within the range of an Imm16 operand, so
219f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // commit reservation putting the offset into the constant pool,
220f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // and update the jump instruction and operand.
22113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    size_t entry = constant_array_builder()->CommitReservedEntry(
222f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        OperandSize::kShort, Smi::FromInt(delta));
223f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    jump_bytecode = GetJumpWithConstantOperand(jump_bytecode);
224f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    bytecodes()->at(jump_location) = Bytecodes::ToByte(jump_bytecode);
22513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(entry));
22613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
22713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(bytecodes()->at(operand_location) == k8BitJumpPlaceholder &&
22813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch         bytecodes()->at(operand_location + 1) == k8BitJumpPlaceholder);
22913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  bytecodes()->at(operand_location++) = operand_bytes[0];
23013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  bytecodes()->at(operand_location) = operand_bytes[1];
23113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
23213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
23313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid BytecodeArrayWriter::PatchJumpWith32BitOperand(size_t jump_location,
23413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                                    int delta) {
23513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(Bytecodes::IsJumpImmediate(
23613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Bytecodes::FromByte(bytecodes()->at(jump_location))));
23713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  constant_array_builder()->DiscardReservedEntry(OperandSize::kQuad);
23813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint8_t operand_bytes[4];
23913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  WriteUnalignedUInt32(operand_bytes, static_cast<uint32_t>(delta));
24013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  size_t operand_location = jump_location + 1;
24113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(bytecodes()->at(operand_location) == k8BitJumpPlaceholder &&
24213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch         bytecodes()->at(operand_location + 1) == k8BitJumpPlaceholder &&
24313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch         bytecodes()->at(operand_location + 2) == k8BitJumpPlaceholder &&
24413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch         bytecodes()->at(operand_location + 3) == k8BitJumpPlaceholder);
24513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  bytecodes()->at(operand_location++) = operand_bytes[0];
24613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  bytecodes()->at(operand_location++) = operand_bytes[1];
24713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  bytecodes()->at(operand_location++) = operand_bytes[2];
24813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  bytecodes()->at(operand_location) = operand_bytes[3];
24913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
25013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
25113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid BytecodeArrayWriter::PatchJump(size_t jump_target, size_t jump_location) {
25213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Bytecode jump_bytecode = Bytecodes::FromByte(bytecodes()->at(jump_location));
25313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int delta = static_cast<int>(jump_target - jump_location);
25413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int prefix_offset = 0;
25513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  OperandScale operand_scale = OperandScale::kSingle;
25613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (Bytecodes::IsPrefixScalingBytecode(jump_bytecode)) {
25713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // If a prefix scaling bytecode is emitted the target offset is one
25813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // less than the case of no prefix scaling bytecode.
25913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    delta -= 1;
26013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    prefix_offset = 1;
26113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    operand_scale = Bytecodes::PrefixBytecodeToOperandScale(jump_bytecode);
26213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    jump_bytecode =
26313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        Bytecodes::FromByte(bytecodes()->at(jump_location + prefix_offset));
26413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
265bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
26613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(Bytecodes::IsJump(jump_bytecode));
26713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  switch (operand_scale) {
26813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case OperandScale::kSingle:
26913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      PatchJumpWith8BitOperand(jump_location, delta);
27013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      break;
27113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case OperandScale::kDouble:
27213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      PatchJumpWith16BitOperand(jump_location + prefix_offset, delta);
27313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      break;
27413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case OperandScale::kQuadruple:
27513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      PatchJumpWith32BitOperand(jump_location + prefix_offset, delta);
27613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      break;
27713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    default:
27813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      UNREACHABLE();
27913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
28013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  unbound_jumps_--;
28113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
28213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
28313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid BytecodeArrayWriter::EmitJump(BytecodeNode* node, BytecodeLabel* label) {
28413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(Bytecodes::IsJump(node->bytecode()));
285c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  DCHECK_EQ(0u, node->operand(0));
28613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
28713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  size_t current_offset = bytecodes()->size();
28813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
28913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (label->is_bound()) {
29013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    CHECK_GE(current_offset, label->offset());
29162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    CHECK_LE(current_offset, static_cast<size_t>(kMaxUInt32));
29213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // Label has been bound already so this is a backwards jump.
29362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    uint32_t delta = static_cast<uint32_t>(current_offset - label->offset());
29462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    OperandScale operand_scale = Bytecodes::ScaleForUnsignedOperand(delta);
295f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (operand_scale > OperandScale::kSingle) {
29613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      // Adjust for scaling byte prefix for wide jump offset.
29762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      delta += 1;
29813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
299f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    DCHECK_EQ(Bytecode::kJumpLoop, node->bytecode());
30062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    node->update_operand0(delta);
30113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else {
30213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // The label has not yet been bound so this is a forward reference
30313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // that will be patched when the label is bound. We create a
30413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // reservation in the constant pool so the jump can be patched
30513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // when the label is bound. The reservation means the maximum size
30613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // of the operand for the constant is known and the jump can
30713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // be emitted into the bytecode stream with space for the operand.
30813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    unbound_jumps_++;
30913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    label->set_referrer(current_offset);
31013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    OperandSize reserved_operand_size =
31113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        constant_array_builder()->CreateReservedEntry();
312f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    DCHECK_NE(Bytecode::kJumpLoop, node->bytecode());
31313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    switch (reserved_operand_size) {
31413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      case OperandSize::kNone:
31513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        UNREACHABLE();
31613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        break;
31713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      case OperandSize::kByte:
31862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        node->update_operand0(k8BitJumpPlaceholder);
31913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        break;
32013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      case OperandSize::kShort:
32162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        node->update_operand0(k16BitJumpPlaceholder);
32213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        break;
32313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      case OperandSize::kQuad:
32462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        node->update_operand0(k32BitJumpPlaceholder);
32513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        break;
32613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
32713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
32813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  EmitBytecode(node);
329bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
330bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
331bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}  // namespace interpreter
332bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}  // namespace internal
333bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}  // namespace v8
334