Skip to content

Commit

Permalink
feat(avm)!: use 32 bit locations (#9596)
Browse files Browse the repository at this point in the history
Contrary to what was expected months ago, we have to support contracts > 65 kB. So we need 32 bit locations in the upcoming move to byte-indexed PCs. This increseases bytecode ~8% in the short term. In the longer term, we might introduce relative jumps with 8 and 16 bit variants. That would likely leave us in an even better place than where we are today.

Part of #9059.
  • Loading branch information
fcarreiro authored Oct 30, 2024
1 parent 0c5121f commit 5f38696
Show file tree
Hide file tree
Showing 13 changed files with 53 additions and 53 deletions.
8 changes: 4 additions & 4 deletions avm-transpiler/src/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ pub enum AvmOpcode {
RETURNDATASIZE,
RETURNDATACOPY,
// Control flow
JUMP_16,
JUMPI_16,
JUMP_32,
JUMPI_32,
INTERNALCALL,
INTERNALRETURN,
// Memory
Expand Down Expand Up @@ -130,8 +130,8 @@ impl AvmOpcode {

// Machine State
// Machine State - Internal Control Flow
AvmOpcode::JUMP_16 => "JUMP_16",
AvmOpcode::JUMPI_16 => "JUMPI_16",
AvmOpcode::JUMP_32 => "JUMP_32",
AvmOpcode::JUMPI_32 => "JUMPI_32",
AvmOpcode::INTERNALCALL => "INTERNALCALL",
AvmOpcode::INTERNALRETURN => "INTERNALRETURN",
// Machine State - Memory
Expand Down
10 changes: 5 additions & 5 deletions avm-transpiler/src/transpile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,20 +233,20 @@ pub fn brillig_to_avm(
BrilligOpcode::Jump { location } => {
let avm_loc = brillig_pcs_to_avm_pcs[*location];
avm_instrs.push(AvmInstruction {
opcode: AvmOpcode::JUMP_16,
operands: vec![make_operand(16, &avm_loc)],
opcode: AvmOpcode::JUMP_32,
operands: vec![make_operand(32, &avm_loc)],
..Default::default()
});
}
BrilligOpcode::JumpIf { condition, location } => {
let avm_loc = brillig_pcs_to_avm_pcs[*location];
avm_instrs.push(AvmInstruction {
opcode: AvmOpcode::JUMPI_16,
opcode: AvmOpcode::JUMPI_32,
indirect: Some(
AddressingModeBuilder::default().direct_operand(condition).build(),
),
operands: vec![
make_operand(16, &avm_loc),
make_operand(32, &avm_loc),
make_operand(16, &condition.to_usize()),
],
..Default::default()
Expand Down Expand Up @@ -298,7 +298,7 @@ pub fn brillig_to_avm(
let avm_loc = brillig_pcs_to_avm_pcs[*location];
avm_instrs.push(AvmInstruction {
opcode: AvmOpcode::INTERNALCALL,
operands: vec![AvmOperand::U16 { value: avm_loc as u16 }],
operands: vec![AvmOperand::U32 { value: avm_loc as u32 }],
..Default::default()
});
}
Expand Down
22 changes: 11 additions & 11 deletions barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ TEST_F(AvmExecutionTests, simpleInternalCall)
"0D3D2518" // val 222111000 = 0xD3D2518
"0004" // dst_offset 4
+ to_hex(OpCode::INTERNALCALL) + // opcode INTERNALCALL
"0004" // jmp_dest
"00000004" // jmp_dest
+ to_hex(OpCode::ADD_16) + // opcode ADD
"00" // Indirect flag
"0004" // addr a 4
Expand Down Expand Up @@ -351,7 +351,7 @@ TEST_F(AvmExecutionTests, simpleInternalCall)
// INTERNALCALL
EXPECT_THAT(instructions.at(1),
AllOf(Field(&Instruction::op_code, OpCode::INTERNALCALL),
Field(&Instruction::operands, ElementsAre(VariantWith<uint16_t>(4)))));
Field(&Instruction::operands, ElementsAre(VariantWith<uint32_t>(4)))));

// INTERNALRETURN
EXPECT_EQ(instructions.at(5).op_code, OpCode::INTERNALRETURN);
Expand Down Expand Up @@ -388,7 +388,7 @@ TEST_F(AvmExecutionTests, nestedInternalCalls)
{
auto internalCallInstructionHex = [](std::string const& dst_offset) {
return to_hex(OpCode::INTERNALCALL) // opcode INTERNALCALL
+ "00" + dst_offset;
+ "000000" + dst_offset;
};

auto setInstructionHex = [](std::string const& val, std::string const& dst_offset) {
Expand Down Expand Up @@ -471,8 +471,8 @@ TEST_F(AvmExecutionTests, jumpAndCalldatacopy)
"0000" // cd_offset
"0001" // copy_size
"000A" // dst_offset // M[10] = 13, M[11] = 156
+ to_hex(OpCode::JUMP_16) + // opcode JUMP
"0005" // jmp_dest (FDIV located at 3)
+ to_hex(OpCode::JUMP_32) + // opcode JUMP
"00000005" // jmp_dest (FDIV located at 3)
+ to_hex(OpCode::SUB_8) + // opcode SUB
"00" // Indirect flag
"0B" // addr 11
Expand Down Expand Up @@ -507,8 +507,8 @@ TEST_F(AvmExecutionTests, jumpAndCalldatacopy)

// JUMP
EXPECT_THAT(instructions.at(3),
AllOf(Field(&Instruction::op_code, OpCode::JUMP_16),
Field(&Instruction::operands, ElementsAre(VariantWith<uint16_t>(5)))));
AllOf(Field(&Instruction::op_code, OpCode::JUMP_32),
Field(&Instruction::operands, ElementsAre(VariantWith<uint32_t>(5)))));

std::vector<FF> returndata;
ExecutionHints execution_hints;
Expand Down Expand Up @@ -566,9 +566,9 @@ TEST_F(AvmExecutionTests, jumpiAndCalldatacopy)
+ to_hex(AvmMemoryTag::U16) +
"14" // val 20
"65" // dst_offset 101
+ to_hex(OpCode::JUMPI_16) + // opcode JUMPI
+ to_hex(OpCode::JUMPI_32) + // opcode JUMPI
"00" // Indirect flag
"0006" // jmp_dest (MUL located at 6)
"00000006" // jmp_dest (MUL located at 6)
"000A" // cond_offset 10
+ to_hex(OpCode::ADD_16) + // opcode ADD
"00" // Indirect flag
Expand Down Expand Up @@ -596,9 +596,9 @@ TEST_F(AvmExecutionTests, jumpiAndCalldatacopy)
// JUMPI
EXPECT_THAT(
instructions.at(4),
AllOf(Field(&Instruction::op_code, OpCode::JUMPI_16),
AllOf(Field(&Instruction::op_code, OpCode::JUMPI_32),
Field(&Instruction::operands,
ElementsAre(VariantWith<uint8_t>(0), VariantWith<uint16_t>(6), VariantWith<uint16_t>(10)))));
ElementsAre(VariantWith<uint8_t>(0), VariantWith<uint32_t>(6), VariantWith<uint16_t>(10)))));

std::vector<FF> returndata;
ExecutionHints execution_hints;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ const std::unordered_map<OpCode, std::vector<OperandType>> OPCODE_WIRE_FORMAT =
{ OperandType::INDIRECT8, OperandType::UINT16, OperandType::UINT16, OperandType::UINT16 } },

// Machine State - Internal Control Flow
{ OpCode::JUMP_16, { OperandType::UINT16 } },
{ OpCode::JUMPI_16, { OperandType::INDIRECT8, OperandType::UINT16, OperandType::UINT16 } },
{ OpCode::INTERNALCALL, { OperandType::UINT16 } },
{ OpCode::JUMP_32, { OperandType::UINT32 } },
{ OpCode::JUMPI_32, { OperandType::INDIRECT8, OperandType::UINT32, OperandType::UINT16 } },
{ OpCode::INTERNALCALL, { OperandType::UINT32 } },
{ OpCode::INTERNALRETURN, {} },

// Machine State - Memory
Expand Down
10 changes: 5 additions & 5 deletions barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -508,16 +508,16 @@ std::vector<Row> Execution::gen_trace(std::vector<FF> const& calldata,
break;

// Machine State - Internal Control Flow
case OpCode::JUMP_16:
trace_builder.op_jump(std::get<uint16_t>(inst.operands.at(0)));
case OpCode::JUMP_32:
trace_builder.op_jump(std::get<uint32_t>(inst.operands.at(0)));
break;
case OpCode::JUMPI_16:
case OpCode::JUMPI_32:
trace_builder.op_jumpi(std::get<uint8_t>(inst.operands.at(0)),
std::get<uint16_t>(inst.operands.at(1)),
std::get<uint32_t>(inst.operands.at(1)),
std::get<uint16_t>(inst.operands.at(2)));
break;
case OpCode::INTERNALCALL:
trace_builder.op_internal_call(std::get<uint16_t>(inst.operands.at(0)));
trace_builder.op_internal_call(std::get<uint32_t>(inst.operands.at(0)));
break;
case OpCode::INTERNALRETURN:
trace_builder.op_internal_return();
Expand Down
4 changes: 2 additions & 2 deletions barretenberg/cpp/src/barretenberg/vm/avm/trace/fixed_gas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ const std::unordered_map<OpCode, FixedGasTable::GasRow> GAS_COST_TABLE = {
{ OpCode::CALLDATACOPY, make_cost(AVM_CALLDATACOPY_BASE_L2_GAS, 0, AVM_CALLDATACOPY_DYN_L2_GAS, 0) },
{ OpCode::RETURNDATASIZE, make_cost(AVM_RETURNDATASIZE_BASE_L2_GAS, 0, 0, 0) },
{ OpCode::RETURNDATACOPY, make_cost(AVM_RETURNDATACOPY_BASE_L2_GAS, 0, AVM_RETURNDATACOPY_DYN_L2_GAS, 0) },
{ OpCode::JUMP_16, make_cost(AVM_JUMP_BASE_L2_GAS, 0, 0, 0) },
{ OpCode::JUMPI_16, make_cost(AVM_JUMPI_BASE_L2_GAS, 0, 0, 0) },
{ OpCode::JUMP_32, make_cost(AVM_JUMP_BASE_L2_GAS, 0, 0, 0) },
{ OpCode::JUMPI_32, make_cost(AVM_JUMPI_BASE_L2_GAS, 0, 0, 0) },
{ OpCode::INTERNALCALL, make_cost(AVM_INTERNALCALL_BASE_L2_GAS, 0, 0, 0) },
{ OpCode::INTERNALRETURN, make_cost(AVM_INTERNALRETURN_BASE_L2_GAS, 0, 0, 0) },
{ OpCode::SET_8, make_cost(AVM_SET_BASE_L2_GAS, 0, 0, 0) },
Expand Down
8 changes: 4 additions & 4 deletions barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,10 @@ std::string to_string(OpCode opcode)
return "CALLDATACOPY";
// Machine State
// Machine State - Internal Control Flow
case OpCode::JUMP_16:
return "JUMP_16";
case OpCode::JUMPI_16:
return "JUMPI_16";
case OpCode::JUMP_32:
return "JUMP_32";
case OpCode::JUMPI_32:
return "JUMPI_32";
case OpCode::INTERNALCALL:
return "INTERNALCALL";
case OpCode::INTERNALRETURN:
Expand Down
4 changes: 2 additions & 2 deletions barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ enum class OpCode : uint8_t {

// Machine State
// Machine State - Internal Control Flow
JUMP_16,
JUMPI_16,
JUMP_32,
JUMPI_32,
INTERNALCALL,
INTERNALRETURN,
// Machine State - Memory
Expand Down
4 changes: 2 additions & 2 deletions barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1695,7 +1695,7 @@ void AvmTraceBuilder::op_jump(uint32_t jmp_dest, bool skip_gas)

// Constrain gas cost
if (!skip_gas) {
gas_trace_builder.constrain_gas(clk, OpCode::JUMP_16);
gas_trace_builder.constrain_gas(clk, OpCode::JUMP_32);
}

main_trace.push_back(Row{
Expand Down Expand Up @@ -1739,7 +1739,7 @@ void AvmTraceBuilder::op_jumpi(uint8_t indirect, uint32_t jmp_dest, uint32_t con
uint32_t next_pc = !id_zero ? jmp_dest : pc + 1;

// Constrain gas cost
gas_trace_builder.constrain_gas(clk, OpCode::JUMPI_16);
gas_trace_builder.constrain_gas(clk, OpCode::JUMPI_32);

main_trace.push_back(Row{
.main_clk = clk,
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/simulator/src/avm/avm_gas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ const BASE_GAS_COSTS: Record<Opcode, Gas> = {
[Opcode.CALLDATACOPY]: makeCost(c.AVM_CALLDATACOPY_BASE_L2_GAS, 0),
[Opcode.RETURNDATASIZE]: makeCost(c.AVM_RETURNDATASIZE_BASE_L2_GAS, 0),
[Opcode.RETURNDATACOPY]: makeCost(c.AVM_RETURNDATACOPY_BASE_L2_GAS, 0),
[Opcode.JUMP_16]: makeCost(c.AVM_JUMP_BASE_L2_GAS, 0),
[Opcode.JUMPI_16]: makeCost(c.AVM_JUMPI_BASE_L2_GAS, 0),
[Opcode.JUMP_32]: makeCost(c.AVM_JUMP_BASE_L2_GAS, 0),
[Opcode.JUMPI_32]: makeCost(c.AVM_JUMPI_BASE_L2_GAS, 0),
[Opcode.INTERNALCALL]: makeCost(c.AVM_INTERNALCALL_BASE_L2_GAS, 0),
[Opcode.INTERNALRETURN]: makeCost(c.AVM_INTERNALRETURN_BASE_L2_GAS, 0),
[Opcode.SET_8]: makeCost(c.AVM_SET_BASE_L2_GAS, 0),
Expand Down
12 changes: 6 additions & 6 deletions yarn-project/simulator/src/avm/opcodes/control_flow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ describe('Control Flow Opcodes', () => {
it('Should (de)serialize correctly', () => {
const buf = Buffer.from([
Jump.opcode, // opcode
...Buffer.from('1234', 'hex'), // loc
...Buffer.from('12340000', 'hex'), // loc
]);
const inst = new Jump(/*loc=*/ 0x1234);
const inst = new Jump(/*loc=*/ 0x12340000);

expect(Jump.deserialize(buf)).toEqual(inst);
expect(inst.serialize()).toEqual(buf);
Expand All @@ -39,10 +39,10 @@ describe('Control Flow Opcodes', () => {
const buf = Buffer.from([
JumpI.opcode, // opcode
0x01, // indirect
...Buffer.from('1234', 'hex'), // loc
...Buffer.from('12340000', 'hex'), // loc
...Buffer.from('a234', 'hex'), // condOffset
]);
const inst = new JumpI(/*indirect=*/ 1, /*loc=*/ 0x1234, /*condOffset=*/ 0xa234);
const inst = new JumpI(/*indirect=*/ 1, /*loc=*/ 0x12340000, /*condOffset=*/ 0xa234);

expect(JumpI.deserialize(buf)).toEqual(inst);
expect(inst.serialize()).toEqual(buf);
Expand Down Expand Up @@ -84,9 +84,9 @@ describe('Control Flow Opcodes', () => {
it('INTERNALCALL Should (de)serialize correctly', () => {
const buf = Buffer.from([
InternalCall.opcode, // opcode
...Buffer.from('1234', 'hex'), // loc
...Buffer.from('12340000', 'hex'), // loc
]);
const inst = new InternalCall(/*loc=*/ 0x1234);
const inst = new InternalCall(/*loc=*/ 0x12340000);

expect(InternalCall.deserialize(buf)).toEqual(inst);
expect(inst.serialize()).toEqual(buf);
Expand Down
10 changes: 5 additions & 5 deletions yarn-project/simulator/src/avm/opcodes/control_flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import { Instruction } from './instruction.js';

export class Jump extends Instruction {
static type: string = 'JUMP';
static readonly opcode: Opcode = Opcode.JUMP_16;
static readonly opcode: Opcode = Opcode.JUMP_32;
// Informs (de)serialization. See Instruction.deserialize.
static readonly wireFormat: OperandType[] = [OperandType.UINT8, OperandType.UINT16];
static readonly wireFormat: OperandType[] = [OperandType.UINT8, OperandType.UINT32];

constructor(private jumpOffset: number) {
super();
Expand All @@ -26,13 +26,13 @@ export class Jump extends Instruction {

export class JumpI extends Instruction {
static type: string = 'JUMPI';
static readonly opcode: Opcode = Opcode.JUMPI_16;
static readonly opcode: Opcode = Opcode.JUMPI_32;

// Instruction wire format with opcode.
static readonly wireFormat: OperandType[] = [
OperandType.UINT8,
OperandType.UINT8,
OperandType.UINT16,
OperandType.UINT32,
OperandType.UINT16,
];

Expand Down Expand Up @@ -63,7 +63,7 @@ export class InternalCall extends Instruction {
static readonly type: string = 'INTERNALCALL';
static readonly opcode: Opcode = Opcode.INTERNALCALL;
// Informs (de)serialization. See Instruction.deserialize.
static readonly wireFormat: OperandType[] = [OperandType.UINT8, OperandType.UINT16];
static readonly wireFormat: OperandType[] = [OperandType.UINT8, OperandType.UINT32];

constructor(private loc: number) {
super();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ export enum Opcode {
RETURNDATASIZE,
RETURNDATACOPY,
// Control flow
JUMP_16,
JUMPI_16,
JUMP_32,
JUMPI_32,
INTERNALCALL,
INTERNALRETURN,
// Memory
Expand Down

0 comments on commit 5f38696

Please sign in to comment.