(
instructions: &[Instruction],
initial_locals: &[FrameValue],
local_hints: &[FrameValue],
max_locals: usize,
constant_pool: &ConstantPool,
context: &str,
)
| 387 | initial_locals: &[FrameValue], |
| 388 | local_hints: &[FrameValue], |
| 389 | max_locals: u16, |
| 390 | constant_pool: &ConstantPool, |
| 391 | context: &str, |
| 392 | exception_table: &mut [ExceptionTableEntry], |
| 393 | ) -> jvm::Result<(usize, FrameAnalysis)> { |
| 394 | if instructions.is_empty() { |
| 395 | return Ok(( |
| 396 | 0, |
| 397 | FrameAnalysis { |
| 398 | block_starts: Vec::new(), |
| 399 | entry_states: Vec::new(), |
| 400 | }, |
| 401 | )); |
| 402 | } |
| 403 | |
| 404 | let locals = locals_loaded_before_definite_store( |
| 405 | instructions, |
| 406 | initial_locals, |
| 407 | max_locals as usize, |
| 408 | context, |
| 409 | exception_table, |
| 410 | )?; |
| 411 | if locals.is_empty() { |
| 412 | let analysis = solve_frame_states( |
| 413 | instructions, |
| 414 | initial_locals, |
| 415 | local_hints, |
| 416 | max_locals as usize, |
| 417 | constant_pool, |
| 418 | context, |
| 419 | exception_table, |
| 420 | )?; |
| 421 | return Ok((0, analysis)); |
| 422 | } |
| 423 | |
| 424 | let mut prefix = Vec::with_capacity(locals.len() * 2); |
| 425 | for (local, value) in locals { |
| 426 | prefix.extend(default_local_initializer(local, &value)); |
| 427 | } |
| 428 | let prefix_len = u16::try_from(prefix.len()).map_err(|_| jvm::Error::VerificationError { |
| 429 | context: context.to_string(), |
| 430 | message: "Verifier local-initialization prefix exceeds the JVM instruction limit" |
| 431 | .to_string(), |
| 432 | })?; |
| 433 | shift_absolute_branch_targets(instructions, prefix_len, context)?; |
| 434 | instructions.splice(0..0, prefix); |
| 435 | shift_exception_table(exception_table, prefix_len, context)?; |
| 436 | |
| 437 | let remaining = locals_loaded_before_definite_store( |
| 438 | instructions, |
| 439 | initial_locals, |
| 440 | max_locals as usize, |
no test coverage detected