def interpret(self, method, frame): current_bc_idx = 0 while True: # since methods cannot contain loops (all loops are done via primitives) # profiling only needs to be done on pc = 0 if current_bc_idx == 0: jitdriver.can_enter_jit(bytecode_index=current_bc_idx, interp=self, method=method, frame=frame) jitdriver.jit_merge_point(bytecode_index=current_bc_idx, interp=self, method=method, frame=frame) bytecode = method.get_bytecode(current_bc_idx) # Get the length of the current bytecode bc_length = bytecode_length(bytecode) # Compute the next bytecode index next_bc_idx = current_bc_idx + bc_length # Handle the current bytecode if bytecode == Bytecodes.halt: # BC: 0 return frame.get_stack_element(0) elif bytecode == Bytecodes.dup: # BC: 1 self._do_dup(frame, method) elif bytecode == Bytecodes.push_local: # BC: 2 self._do_push_local(current_bc_idx, frame, method) elif bytecode == Bytecodes.push_argument: # BC: 3 self._do_push_argument(current_bc_idx, frame, method) elif bytecode == Bytecodes.push_field: # BC: 4 self._do_push_field(current_bc_idx, frame, method) elif bytecode == Bytecodes.push_block: # BC: 5 self._do_push_block(current_bc_idx, frame, method) elif bytecode == Bytecodes.push_constant: # BC: 6 self._do_push_constant(current_bc_idx, frame, method) elif bytecode == Bytecodes.push_global: # BC: 7 self._do_push_global(current_bc_idx, frame, method) elif bytecode == Bytecodes.pop: # BC: 8 self._do_pop(frame) elif bytecode == Bytecodes.pop_local: # BC: 9 self._do_pop_local(current_bc_idx, frame, method) elif bytecode == Bytecodes.pop_argument: # BC:10 self._do_pop_argument(current_bc_idx, frame, method) elif bytecode == Bytecodes.pop_field: # BC:11 self._do_pop_field(current_bc_idx, frame, method) elif bytecode == Bytecodes.send: # BC:12 self._do_send(current_bc_idx, frame, method) elif bytecode == Bytecodes.super_send: # BC:13 self._do_super_send(current_bc_idx, frame, method) elif bytecode == Bytecodes.return_local: # BC:14 return self._do_return_local(frame) elif bytecode == Bytecodes.return_non_local: # BC:15 return self._do_return_non_local(frame) current_bc_idx = next_bc_idx
def _compute_stack_depth(self): depth = 0 max_depth = 0 i = 0 while i < len(self._bytecode): bc = self._bytecode[i] if bytecode_stack_effect_depends_on_send(bc): signature = self._literals[self._bytecode[i + 1]] depth += bytecode_stack_effect(bc, signature.get_number_of_signature_arguments()) else: depth += bytecode_stack_effect(bc) i += bytecode_length(bc) if depth > max_depth: max_depth = depth return max_depth
def _compute_stack_depth(self): depth = 0 max_depth = 0 i = 0 while i < len(self._bytecode): bc = self._bytecode[i] if bytecode_stack_effect_depends_on_send(bc): signature = self._literals[self._bytecode[i + 1]] depth += bytecode_stack_effect( bc, signature.get_number_of_signature_arguments()) else: depth += bytecode_stack_effect(bc) i += bytecode_length(bc) if depth > max_depth: max_depth = depth return max_depth
def interpret(self, method, frame): current_bc_idx = 0 while True: # since methods cannot contain loops (all loops are done via primitives) # profiling only needs to be done on pc = 0 if current_bc_idx == 0: jitdriver.can_enter_jit(bytecode_index=current_bc_idx, interp=self, method=method, frame=frame) jitdriver.jit_merge_point(bytecode_index=current_bc_idx, interp=self, method=method, frame=frame) bytecode = method.get_bytecode(current_bc_idx) # Get the length of the current bytecode bc_length = bytecode_length(bytecode) # Compute the next bytecode index next_bc_idx = current_bc_idx + bc_length # Handle the current bytecode if bytecode == Bytecodes.halt: # BC: 0 return frame.get_stack_element(0) elif bytecode == Bytecodes.dup: # BC: 1 self._do_dup(frame, method) elif bytecode == Bytecodes.push_local: # BC: 2 self._do_push_local(current_bc_idx, frame, method) elif bytecode == Bytecodes.push_argument: # BC: 3 self._do_push_argument(current_bc_idx, frame, method) elif bytecode == Bytecodes.push_field: # BC: 4 self._do_push_field(current_bc_idx, frame, method) elif bytecode == Bytecodes.push_block: # BC: 5 self._do_push_block(current_bc_idx, frame, method) elif bytecode == Bytecodes.push_constant: # BC: 6 self._do_push_constant(current_bc_idx, frame, method) elif bytecode == Bytecodes.push_global: # BC: 7 self._do_push_global(current_bc_idx, frame, method) elif bytecode == Bytecodes.pop: # BC: 8 self._do_pop(frame) elif bytecode == Bytecodes.pop_local: # BC: 9 self._do_pop_local(current_bc_idx, frame, method) elif bytecode == Bytecodes.pop_argument: # BC:10 self._do_pop_argument(current_bc_idx, frame, method) elif bytecode == Bytecodes.pop_field: # BC:11 self._do_pop_field(current_bc_idx, frame, method) elif bytecode == Bytecodes.send: # BC:12 self._do_send(current_bc_idx, frame, method) elif bytecode == Bytecodes.super_send: # BC:13 self._do_super_send(current_bc_idx, frame, method) elif bytecode == Bytecodes.return_local: # BC:14 return self._do_return_local(frame) elif bytecode == Bytecodes.return_non_local: # BC:15 return self._do_return_non_local(frame) elif bytecode == Bytecodes.add: self._do_add(current_bc_idx, frame, method) elif bytecode == Bytecodes.multiply: self._do_multiply(current_bc_idx, frame, method) elif bytecode == Bytecodes.subtract: self._do_subtract(current_bc_idx, frame, method) current_bc_idx = next_bc_idx
def dump_method(m, indent): error_println("(") # output stack information error_println("%s<%d locals, %d stack, %d bc_count>" % (indent, m.get_number_of_locals().get_embedded_integer(), m.get_maximum_number_of_stack_elements().get_embedded_integer(), m.get_number_of_bytecodes())) # output bytecodes b = 0 while b < m.get_number_of_bytecodes(): error_print(indent) # bytecode index if b < 10: error_print(" ") if b < 100: error_print(" ") error_print(" %d:" % b) # mnemonic bytecode = m.get_bytecode(b) error_print(bytecode_as_str(bytecode) + " ") # parameters (if any) if bytecode_length(bytecode) == 1: error_println() b += 1 continue if bytecode == Bytecodes.push_local: error_println("local: " + str(m.get_bytecode(b + 1)) + ", context: " + str(m.get_bytecode(b + 2))) elif bytecode == Bytecodes.push_argument: error_println("argument: " + str(m.get_bytecode(b + 1)) + ", context " + str(m.get_bytecode(b + 2))) elif bytecode == Bytecodes.push_field: error_println("(index: " + str(m.get_bytecode(b + 1)) + ") field: " + str(m.get_holder().get_instance_field_name(m.get_bytecode(b + 1)))) elif bytecode == Bytecodes.push_block: error_print("block: (index: " + str(m.get_bytecode(b + 1)) + ") ") dump_method(m.get_constant(b), indent + "\t") elif bytecode == Bytecodes.push_constant: constant = m.get_constant(b) error_println("(index: " + str(m.get_bytecode(b + 1)) + ") value: (" + str(constant.get_class(get_current()).get_name()) + ") " + str(constant)) elif bytecode == Bytecodes.push_global: error_println("(index: " + str(m.get_bytecode(b + 1)) + ") value: " + str(m.get_constant(b))) elif bytecode == Bytecodes.pop_local: error_println("local: " + str(m.get_bytecode(b + 1)) + ", context: " + str(m.get_bytecode(b + 2))) elif bytecode == Bytecodes.pop_argument: error_println("argument: " + str(m.get_bytecode(b + 1)) + ", context: " + str(m.get_bytecode(b + 2))) elif bytecode == Bytecodes.pop_field: error_println("(index: " + str(m.get_bytecode(b + 1)) + ") field: " + str(m.get_holder().get_instance_field_name(m.get_bytecode(b + 1)))) elif bytecode == Bytecodes.send: error_println("(index: " + str(m.get_bytecode(b + 1)) + ") signature: " + str(m.get_constant(b))) elif bytecode == Bytecodes.super_send: error_println("(index: " + str(m.get_bytecode(b + 1)) + ") signature: " + str(m.get_constant(b))) else: error_println("<incorrect bytecode>") b += bytecode_length(m.get_bytecode(b)) error_println(indent + ")")