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