home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #4 / amigaacscoverdisc1998-041998.iso / utilities / shareware / dev / ppcsmalleiffel / lib_se / jvm.e < prev    next >
Encoding:
Text File  |  1998-01-16  |  19.5 KB  |  885 lines

  1. --          This file is part of SmallEiffel The GNU Eiffel Compiler.
  2. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  3. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr 
  4. --                       http://www.loria.fr/SmallEiffel
  5. -- SmallEiffel is  free  software;  you can  redistribute it and/or modify it 
  6. -- under the terms of the GNU General Public License as published by the Free
  7. -- Software  Foundation;  either  version  2, or (at your option)  any  later 
  8. -- version. SmallEiffel is distributed in the hope that it will be useful,but
  9. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. -- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License 
  11. -- for  more  details.  You  should  have  received a copy of the GNU General 
  12. -- Public  License  along  with  SmallEiffel;  see the file COPYING.  If not,
  13. -- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14. -- Boston, MA 02111-1307, USA.
  15. --
  16. class JVM
  17.    --
  18.    -- Handling of Java Virtual Machine byte code generation.
  19.    --
  20.  
  21. inherit CODE_PRINTER;
  22.  
  23. creation make 
  24.  
  25. feature
  26.  
  27.    output_name: STRING;
  28.      -- This name is used as the name of the main output class 
  29.      -- file and as the name of the directory used to store
  30.      -- auxilliary class files.
  31.    
  32. feature {NONE}
  33.  
  34.    b_put_u1_count: INTEGER;
  35.      -- To count printed bytes.
  36.  
  37. feature {NONE}
  38.  
  39.    make is do end;
  40.  
  41. feature {NONE}
  42.  
  43.    fields: FIXED_ARRAY[RUN_FEATURE] is
  44.       once 
  45.      !!Result.with_capacity(4);
  46.       end;
  47.  
  48.    methods: FIXED_ARRAY[RUN_FEATURE] is
  49.       once 
  50.      !!Result.with_capacity(64);
  51.       end;
  52.  
  53. feature {RUN_FEATURE}
  54.  
  55.    add_field(rf: RUN_FEATURE) is
  56.       require
  57.      rf /= Void;
  58.      not fields.fast_has(rf)
  59.       do
  60.      fields.add_last(rf);
  61.       ensure
  62.      fields.fast_has(rf)
  63.       end;
  64.  
  65. feature {RUN_FEATURE,NATIVE}
  66.  
  67.    add_method(rf: RUN_FEATURE) is
  68.       require
  69.      rf /= Void;
  70.      not methods.fast_has(rf)
  71.       do
  72.      methods.add_last(rf);
  73.       ensure
  74.      methods.fast_has(rf)
  75.       end;
  76.  
  77. feature 
  78.  
  79.    set_output_name(n: STRING) is
  80.       do
  81.      output_name := n;
  82.       end;
  83.  
  84. feature {SMALL_EIFFEL}
  85.  
  86.    mkdir(root: RUN_FEATURE) is
  87.      -- Create a new directory to store class files.
  88.       require
  89.      root /= Void;
  90.      small_eiffel.is_ready
  91.       do
  92.      if output_name = Void then
  93.         output_name := root.current_type.base_class_name.to_string;
  94.         output_name := output_name.twin;
  95.         output_name.to_lower;
  96.      end;
  97.      if output_name.has_suffix(class_suffix) then
  98.         output_name.remove_suffix(class_suffix);
  99.      end;
  100.      echo.put_string("Trying to prepare directory %"");
  101.      echo.put_string(output_name);
  102.      echo.put_string("%" to store Java byte code.%N");
  103.      file_tools.mkdir(output_name);
  104.       end;
  105.  
  106.    write_jvm_root_class is
  107.       local
  108.      idx: INTEGER;
  109.      cp: like constant_pool;
  110.       do
  111.      cp := constant_pool;
  112.          start_directory(out_file_path,output_name);
  113.          out_file_path.append(fz_jvm_root);
  114.      out_file_path.append(class_suffix);
  115.      bfw_connect(out_file,out_file_path);
  116.      start_basic;
  117.      access_flags := 1025; -- (ACC_PUBLIC,ACC_ABSTRACT)
  118.      this_class_idx := cp.idx_class2(jvm_root_class);
  119.      super_class_idx := cp.idx_java_lang_object;
  120.      -- Fields :
  121.      args_field;
  122.      manifest_string_pool.jvm_define_fields;
  123.      once_routine_pool.jvm_define_fields;
  124.      if run_control.no_check then
  125.         field_info.add(9,cp.idx_uft8(fz_58),cp.idx_uft8(fz_41));
  126.      end;
  127.      -- Methods :
  128.      --    The initialize method :
  129.      current_frame := Void;
  130.      method_info.start(9,fz_28,fz_29);
  131.      manifest_string_pool.jvm_initialize_fields;
  132.      once_routine_pool.jvm_initialize_fields;
  133.      if run_control.no_check then
  134.         idx := cp.idx_fieldref3(jvm_root_class,fz_58,fz_41);
  135.         code_attribute.opcode_iconst_0;
  136.         code_attribute.opcode_putstatic(idx,-1);
  137.      end;
  138.      code_attribute.opcode_return;
  139.      method_info.finish;
  140.      --    For switches :
  141.      switch_collection.jvm_define;
  142.      finish_class;
  143.       end;
  144.  
  145.    write_main_class(rf3: RUN_FEATURE_3) is
  146.      -- Write Java Byte Code for main class to call `rf3'.
  147.       require
  148.      rf3 /= Void;
  149.      small_eiffel.is_ready
  150.       local
  151.      idx: INTEGER;
  152.      cp: like constant_pool;
  153.      ca: like code_attribute;
  154.       do
  155.      cp := constant_pool;
  156.      ca := code_attribute;
  157.      out_file_path.copy(output_name);
  158.      out_file_path.append(class_suffix);
  159.      bfw_connect(out_file,out_file_path);
  160.      start_basic;
  161.      access_flags := 16; -- (ACC_FINAL)
  162.      this_class_idx := cp.idx_class2(output_name);
  163.      super_class_idx := cp.idx_java_lang_object;
  164.      -- Methods :
  165.      --    The main method :
  166.      current_frame := Void;
  167.      method_info.start(9,fz_main,fz_23);
  168.      set_args_field;
  169.      idx := cp.idx_methodref3(jvm_root_class,fz_28,fz_29);
  170.      ca.opcode_invokestatic(idx,0);
  171.      rf3.run_class.jvm_push_default;
  172.      idx := cp.idx_methodref(rf3);
  173.      ca.opcode_invokevirtual(idx,-1);
  174.      ca.opcode_system_out;
  175.      idx := cp.idx_methodref3(fz_25,fz_42,fz_29);
  176.      ca.opcode_invokevirtual(idx,-1);
  177.      ca.opcode_system_err;
  178.      ca.opcode_invokevirtual(idx,-1);
  179.      ca.opcode_return;
  180.      method_info.finish;
  181.      finish_class;
  182.       end;
  183.  
  184. feature {CODE_ATTRIBUTE}
  185.  
  186.    max_locals: INTEGER is
  187.       do
  188.      if current_frame /= Void then
  189.         Result := current_frame.jvm_max_locals;
  190.      else
  191.         Result := 4;
  192.      end;
  193.       end;
  194.  
  195. feature {NONE}
  196.    
  197.    access_flags: INTEGER;
  198.      -- of the class.
  199.  
  200.    this_class_idx: INTEGER;
  201.  
  202.    super_class_idx: INTEGER;
  203.  
  204.    start_basic is
  205.       do
  206.      fields.clear;
  207.      methods.clear;
  208.      constant_pool.clear;
  209.      field_info.clear;
  210.      method_info.clear;
  211.      b_put_u1_count := 0;
  212.       end;
  213.  
  214. feature {RUN_CLASS}
  215.  
  216.    start_new_class(rc: RUN_CLASS) is
  217.       require
  218.      output_name /= Void
  219.       local
  220.      name_idx, type_idx: INTEGER;
  221.      cp: like constant_pool;
  222.       do
  223.      cp := constant_pool;
  224.      start_basic;
  225.      tmp_string.copy(rc.unqualified_name);
  226.      tmp_string.to_lower;
  227.      start_directory(out_file_path,output_name);
  228.      out_file_path.append(tmp_string);
  229.      out_file_path.append(class_suffix);
  230.      bfw_connect(out_file,out_file_path);
  231.      access_flags := 16;
  232.      this_class_idx := rc.fully_qualified_constant_pool_index;
  233.      super_class_idx := cp.idx_jvm_root_class;
  234.      -- <clinit> :
  235.      method_info.start(9,fz_76,fz_29);
  236.      -- generating_type :
  237.      name_idx := cp.idx_uft8(us_generating_type);
  238.      type_idx := cp.idx_eiffel_string_descriptor;
  239.      field_info.add(9,name_idx,type_idx);
  240.      name_idx := cp.idx_fieldref5(this_class_idx,name_idx,type_idx);
  241.      code_attribute.opcode_aconst_null;
  242.      code_attribute.opcode_putstatic(name_idx,-1);
  243.      -- generator :
  244.      name_idx := cp.idx_uft8(us_generator);
  245.      field_info.add(9,name_idx,type_idx);
  246.      name_idx := cp.idx_fieldref5(this_class_idx,name_idx,type_idx);
  247.      code_attribute.opcode_aconst_null;
  248.      code_attribute.opcode_putstatic(name_idx,-1);
  249.      code_attribute.opcode_return;
  250.      method_info.finish;
  251.      rc.jvm_define_class_invariant;
  252.       end;
  253.  
  254.    finish_class is
  255.      -- Really print the class file.
  256.       do
  257.      put_magic;
  258.      put_minor_version;
  259.      put_major_version;
  260.      constant_pool.write_bytes;
  261.      b_put_u2(access_flags);
  262.      b_put_u2(this_class_idx);
  263.      b_put_u2(super_class_idx);
  264.      -- interfaces_count :
  265.      b_put_u2(0);
  266.      field_info.write_bytes;
  267.      method_info.write_bytes;
  268.      -- attributes_count :
  269.      b_put_u2(0);
  270.      out_file.disconnect;
  271.      echo.print_count("byte",b_put_u1_count);
  272.       end;
  273.  
  274. feature
  275.  
  276.    current_frame: RUN_FEATURE;
  277.      -- Current method or current field.
  278.  
  279. feature {RUN_CLASS,SWITCH_COLLECTION}
  280.  
  281.    set_current_frame(cf: like current_frame) is
  282.       do
  283.      current_frame := cf;
  284.       end;
  285.    
  286. feature
  287.  
  288.    argument_offset_of(an: ARGUMENT_NAME): INTEGER is
  289.       require
  290.      an /= Void
  291.       do
  292.      Result := current_frame.jvm_argument_offset(an);
  293.       ensure
  294.      Result >= 0
  295.       end;
  296.  
  297.    local_offset_of(ln: LOCAL_NAME): INTEGER is
  298.       require
  299.      ln /= Void
  300.       do
  301.      Result := current_frame.jvm_local_variable_offset(ln);
  302.       ensure
  303.      Result >= 0
  304.       end;
  305.  
  306.    result_offset: INTEGER is
  307.       do
  308.      Result := current_frame.jvm_result_offset;
  309.       end;
  310.  
  311. feature {CP_INFO}
  312.  
  313.    b_put_u1(byte: CHARACTER) is
  314.       require
  315.      0 <= byte.code;
  316.      byte.code <= 255
  317.       do
  318.      out_file.put_byte(byte);
  319.      b_put_u1_count := b_put_u1_count + 1;
  320.       end;
  321.  
  322. feature {CONSTANT_POOL,FIELD_INFO,METHOD_INFO}
  323.  
  324.    b_put_u2(u2: INTEGER) is
  325.       do
  326.      b_put_u1((u2 // 256).to_character);
  327.      b_put_u1((u2 \\ 256).to_character);
  328.       ensure
  329.      b_put_u1_count = 2 + old b_put_u1_count
  330.       end;
  331.  
  332. feature {CP_INFO,FIELD_INFO,METHOD_INFO}
  333.  
  334.    b_put_byte_string(str: STRING) is
  335.       require
  336.      str /= Void
  337.       local
  338.      i: INTEGER;
  339.       do
  340.      from
  341.         i := 1;
  342.      until
  343.         i > str.count
  344.      loop
  345.         b_put_u1(str.item(i));
  346.         i := i + 1;
  347.      end;
  348.       ensure
  349.      b_put_u1_count = str.count + old b_put_u1_count
  350.       end;
  351.  
  352. feature {RUN_CLASS}
  353.  
  354.    prepare_fields is
  355.       local
  356.      i: INTEGER;
  357.      rf: RUN_FEATURE;
  358.       do
  359.      from
  360.         i := fields.upper;
  361.      until
  362.         i < 0
  363.      loop
  364.         rf := fields.item(i);
  365.         rf.jvm_define;
  366.         i := i - 1;
  367.      end;
  368.       end;
  369.  
  370.    prepare_methods is
  371.       local
  372.      i: INTEGER;
  373.       do
  374.      from
  375.         i := methods.upper;
  376.      until
  377.         i < 0
  378.      loop
  379.         set_current_frame(methods.item(i));
  380.         current_frame.jvm_define;
  381.         i := i - 1;
  382.      end;
  383.       end;
  384.  
  385. feature {NONE}
  386.  
  387.    put_magic is
  388.      -- CAFEBABE ;-)
  389.       do
  390.      b_put_byte_string("%/202/%/254/%/186/%/190/");
  391.       end;
  392.  
  393.    put_minor_version is
  394.       do
  395.      b_put_u2(3);
  396.       end;
  397.  
  398.    put_major_version is
  399.       do
  400.      b_put_byte_string("%/0/%/45/");
  401.       end;
  402.  
  403. feature {NONE}
  404.  
  405.    args_field is
  406.      -- Define `args' field to store command line arguments.
  407.       local
  408.      args_idx, jaos_idx: INTEGER;
  409.      cp: like constant_pool;
  410.       do
  411.      cp := constant_pool;
  412.      args_idx := cp.idx_uft8(fz_74);
  413.      jaos_idx := cp.idx_uft8(fz_75);
  414.      field_info.add(9,args_idx,jaos_idx);
  415.       end;
  416.  
  417.    set_args_field is
  418.      -- Set `args' field to store command line arguments.
  419.       local
  420.      ca: like code_attribute;
  421.       do
  422.      ca := code_attribute;
  423.      ca.opcode_aload_0;
  424.      ca.opcode_putstatic(args_field_idx,-1);
  425.       end;
  426.  
  427.    args_field_idx: INTEGER is
  428.       local
  429.      cp: like constant_pool;
  430.       do
  431.      cp := constant_pool;
  432.      Result := cp.idx_fieldref3(jvm_root_class,fz_74,fz_75);
  433.       end;
  434.  
  435. feature {NATIVE_SMALL_EIFFEL}
  436.  
  437.    push_se_argc is
  438.       local
  439.      ca: like code_attribute;
  440.       do
  441.      ca := code_attribute;
  442.      ca.opcode_getstatic(args_field_idx,1);
  443.      ca.opcode_arraylength;
  444.      ca.opcode_iconst_1;
  445.      ca.opcode_iadd;
  446.       end;
  447.  
  448.    push_se_argv is
  449.       local
  450.      point1, point2, i: INTEGER;
  451.      ca: like code_attribute;
  452.      arg0: STRING;
  453.       do
  454.      ca := code_attribute;
  455.      ca.opcode_getstatic(args_field_idx,1);
  456.      i := push_ith_argument(1)
  457.      ca.opcode_dup;
  458.      point1 := ca.opcode_ifeq;
  459.      ca.opcode_iconst_1;
  460.      ca.opcode_isub;
  461.      ca.opcode_aaload;
  462.      point2 := ca.opcode_goto;
  463.      ca.resolve_u2_branch(point1);
  464.      ca.opcode_pop;
  465.      if output_name /= Void then
  466.         arg0 := output_name;
  467.      else
  468.         arg0 := run_control.root_class;
  469.      end;
  470.      i := constant_pool.idx_string(arg0);
  471.      ca.opcode_ldc(i);
  472.      ca.resolve_u2_branch(point2);
  473.      ca.opcode_java_string2eiffel_string;
  474.       end;
  475.  
  476.  
  477. feature {NONE}
  478.  
  479.    out_file: BINARY_FILE_WRITE is 
  480.      -- Current output class file.
  481.       once
  482.      !!Result.make;
  483.       end;
  484.  
  485.    out_file_path: STRING is
  486.       once
  487.      !!Result.make(32);
  488.       end;
  489.  
  490.    tmp_string: STRING is
  491.       once
  492.      !!Result.make(16);
  493.       end;
  494.  
  495. feature {CALL_PROC_CALL}
  496.  
  497.    b_put_cpc(cpc: CALL_PROC_CALL) is
  498.       local
  499.      target: EXPRESSION;
  500.      target_type: TYPE;
  501.      running: ARRAY[RUN_CLASS];
  502.      switch: SWITCH;
  503.      rf: RUN_FEATURE;
  504.       do
  505.      target := cpc.target;
  506.      target_type := target.result_type.run_type;
  507.      if target_type.is_expanded then
  508.         push_direct(cpc);
  509.         cpc.run_feature.mapping_jvm;
  510.         pop
  511.      elseif target.is_current then
  512.         push_direct(cpc);
  513.         cpc.run_feature.mapping_jvm;
  514.         pop
  515.      elseif target.is_manifest_string then
  516.         push_direct(cpc);
  517.         cpc.run_feature.mapping_jvm;
  518.         pop
  519.      else
  520.         running := target_type.run_class.running;
  521.         check
  522.            running /= Void
  523.         end;
  524.         if running.count = 1 then
  525.            push_check(cpc);
  526.            rf := cpc.run_feature;
  527.            rf := running.first.dynamic(rf);
  528.            rf.mapping_jvm;
  529.            pop
  530.         else
  531.            switch_count := switch_count + 1;
  532.            switch.jvm_mapping(cpc);
  533.         end;
  534.      end;
  535.       end;
  536.  
  537. feature {RUN_CLASS}
  538.  
  539.    push_expanded_initialize(rf: RUN_FEATURE) is
  540.       do
  541.      stack_push(C_expanded_initialize);
  542.      stack_rf.put(rf,top);
  543.       end;
  544.  
  545.    define_class_invariant_method(ci: CLASS_INVARIANT) is
  546.       require
  547.      run_control.invariant_check;
  548.      ci /= Void
  549.       local
  550.      ca: like code_attribute;
  551.      cp: like constant_pool;
  552.       do
  553.      ca := code_attribute;
  554.      cp := constant_pool;
  555.      method_info.start(17,fz_invariant,fz_29);
  556.      stack_push(C_switch);
  557.      ci.compile_to_jvm(true);
  558.      pop;
  559.      ca.opcode_return;
  560.      method_info.finish;
  561.       end;
  562.  
  563. feature {NATIVE}
  564.  
  565.    inside_twin(cpy: RUN_FEATURE) is
  566.       do
  567.      stack_push(C_inside_twin);
  568.      stack_rf.put(cpy,top);
  569.      cpy.mapping_jvm;
  570.      pop;
  571.       end;
  572.  
  573. feature {CREATION_CALL}
  574.  
  575.    inside_new(rf: RUN_FEATURE; cpc: CALL_PROC_CALL) is
  576.       require
  577.      rf /= Void;
  578.      cpc /= Void
  579.       do
  580.      stack_push(C_inside_new);
  581.      stack_rf.put(rf,top);
  582.      stack_cpc.put(cpc,top);
  583.      rf.mapping_jvm;
  584.      pop;
  585.       end;
  586.  
  587. feature {NONE}
  588.  
  589.    push_direct(cpc: CALL_PROC_CALL) is
  590.       require
  591.      cpc /= Void
  592.       do
  593.      stack_push(C_direct_call);
  594.      stack_cpc.put(cpc,top);
  595.      direct_call_count := direct_call_count + 1;
  596.       end;
  597.  
  598.    push_check(cpc: CALL_PROC_CALL) is
  599.       require
  600.      cpc /= Void
  601.       do
  602.      stack_push(C_check_id);
  603.      stack_cpc.put(cpc,top);
  604.       end;
  605.  
  606. feature {RUN_FEATURE,NATIVE}
  607.  
  608.    target_position: POSITION is
  609.       local
  610.      code: INTEGER;
  611.       do
  612.      code := stack_code.item(top); 
  613.      inspect
  614.         code
  615.      when C_direct_call, C_check_id then 
  616.         Result := stack_cpc.item(top).start_position;
  617.      when C_inside_twin then
  618.      when C_switch then
  619.      when C_expanded_initialize then
  620.      when C_inside_new then
  621.         Result := stack_cpc.item(top).start_position;
  622.      else
  623.      end;
  624.       end;
  625.  
  626.    push_target is
  627.      -- Produce java byte code in order to push target on the
  628.      -- jvm stack.
  629.       local
  630.      code: INTEGER;
  631.       do
  632.      code := stack_code.item(top); 
  633.      inspect
  634.         code
  635.      when C_direct_call then 
  636.         stack_cpc.item(top).target.compile_to_jvm;
  637.      when C_check_id then 
  638.         opcode_check_id_for(stack_cpc.item(top).target);
  639.      when C_switch then
  640.         code_attribute.opcode_aload_0;
  641.      when C_expanded_initialize then
  642.         code_attribute.opcode_dup;
  643.      when C_inside_new then
  644.         code_attribute.opcode_dup;
  645.      when C_inside_twin then
  646.         code_attribute.opcode_aload_1;
  647.      else
  648.         fatal_error("JVM NYI XXX #1");
  649.      end;
  650.       end;
  651.  
  652.    push_target_as_target is
  653.      -- Same as `push_target' but with class invariant check.
  654.       local
  655.      code: INTEGER;
  656.       do
  657.      code := stack_code.item(top); 
  658.      inspect
  659.         code
  660.      when C_direct_call then 
  661.         stack_cpc.item(top).target.compile_target_to_jvm;
  662.      when C_check_id then 
  663.         opcode_check_id_for(stack_cpc.item(top).target);
  664.      when C_switch then
  665.         code_attribute.opcode_aload_0;
  666.      when C_expanded_initialize then
  667.         code_attribute.opcode_dup;
  668.      when C_inside_new then
  669.         code_attribute.opcode_dup;
  670.      when C_inside_twin then
  671.         code_attribute.opcode_aload_1;
  672.      else
  673.         fatal_error("JVM NYI XXX #1");
  674.      end;
  675.       end;
  676.  
  677.    drop_target is
  678.       local
  679.      code: INTEGER;
  680.      cpc: CALL_PROC_CALL;
  681.      e: EXPRESSION;
  682.       do
  683.      code := stack_code.item(top); 
  684.      inspect
  685.         code
  686.      when C_direct_call, C_check_id then 
  687.         cpc := stack_cpc.item(top);
  688.         e ?= cpc;
  689.         if e = Void or else not e.can_be_dropped then
  690.            cpc.target.compile_to_jvm;
  691.            if cpc.run_feature.current_type.jvm_stack_space = 1 then
  692.           code_attribute.opcode_pop;
  693.            else
  694.           code_attribute.opcode_pop2;
  695.            end;
  696.         end;
  697.      when C_switch then
  698.      when C_expanded_initialize then
  699.      when C_inside_new then
  700.      when C_inside_twin then
  701.      else
  702.         fatal_error("JVM NYI XXX #812451");
  703.      end;
  704.       end;
  705.  
  706.    drop_ith_argument(i: INTEGER) is
  707.       local
  708.      space: INTEGER;
  709.       do
  710.      from
  711.         space := push_ith_argument(i);
  712.      until
  713.         space = 0
  714.      loop
  715.         code_attribute.opcode_pop;
  716.         space := space - 1;
  717.      end;
  718.       end;
  719.  
  720.    push_arguments: INTEGER is
  721.       local
  722.      code: INTEGER;
  723.      cpc: CALL_PROC_CALL;
  724.      eal: EFFECTIVE_ARG_LIST;
  725.      rf, dyn_rf: RUN_FEATURE;
  726.      fal: FORMAL_ARG_LIST;
  727.       do
  728.      code := stack_code.item(top); 
  729.      inspect
  730.         code
  731.      when C_direct_call, C_check_id then 
  732.         cpc := stack_cpc.item(top);
  733.         eal := cpc.arguments;
  734.         if eal /= Void then
  735.            rf := cpc.run_feature;
  736.            fal := rf.arguments;
  737.            Result := eal.compile_to_jvm(fal);
  738.         end;
  739.      when C_switch then
  740.         rf := stack_static_rf.item(top);
  741.         dyn_rf := stack_rf.item(top);
  742.         fal := rf.arguments;
  743.         if fal /= Void then
  744.            Result := fal.jvm_switch_push(dyn_rf.arguments);
  745.         end;
  746.      when C_expanded_initialize then
  747.         check
  748.            false
  749.         end;
  750.      when C_inside_new then
  751.         cpc := stack_cpc.item(top);
  752.         eal := cpc.arguments;
  753.         if eal /= Void then
  754.            rf := stack_rf.item(top);
  755.            fal := rf.arguments;
  756.            Result := eal.compile_to_jvm(fal);
  757.         end;
  758.      when C_inside_twin then
  759.         Result := push_ith_argument(1);
  760.      else
  761.         fatal_error("JVM NYI XXX #3");
  762.      end;
  763.       end;
  764.  
  765.    push_ith_argument(i: INTEGER): INTEGER is
  766.       local
  767.      code: INTEGER;
  768.      cpc: CALL_PROC_CALL;
  769.      eal: EFFECTIVE_ARG_LIST;
  770.      rf, dyn_rf: RUN_FEATURE;
  771.      fal: FORMAL_ARG_LIST;
  772.       do
  773.      code := stack_code.item(top); 
  774.      inspect
  775.         code
  776.      when C_direct_call, C_check_id then 
  777.         cpc := stack_cpc.item(top);
  778.         eal := cpc.arguments;
  779.         if eal /= Void then
  780.            rf := cpc.run_feature;
  781.            fal := rf.arguments;
  782.            Result := eal.compile_to_jvm_ith(fal,i);
  783.         end;
  784.      when C_switch then
  785.         rf := stack_static_rf.item(top);
  786.         dyn_rf := stack_rf.item(top);
  787.         fal := rf.arguments;
  788.         if fal /= Void then
  789.            Result := fal.jvm_switch_push_ith(dyn_rf.arguments,i);
  790.         end;
  791.      when C_expanded_initialize then
  792.         check
  793.            false
  794.         end;
  795.      when C_inside_new then
  796.         cpc := stack_cpc.item(top);
  797.         eal := cpc.arguments;
  798.         if eal /= Void then
  799.            rf := stack_rf.item(top);
  800.            fal := rf.arguments;
  801.            Result := eal.compile_to_jvm_ith(fal,i);
  802.         end;
  803.      when C_inside_twin then
  804.         code_attribute.opcode_aload_0;
  805.         Result := 1;
  806.      else
  807.         fatal_error("JVM NYI XXX #5");
  808.      end;
  809.       end;
  810.  
  811. feature {SWITCH}
  812.  
  813.    push_switch(rf, static_rf: RUN_FEATURE) is
  814.       require
  815.      rf /= Void;
  816.      static_rf /= Void;
  817.      rf.run_class.dynamic(static_rf) = rf
  818.       do
  819.      stack_push(C_switch);
  820.      stack_rf.put(rf,top);
  821.      stack_static_rf.put(static_rf,top);
  822.       end;
  823.  
  824. feature {NONE}
  825.  
  826.    opcode_check_id_for(e: EXPRESSION) is
  827.      -- Produce code for `e' with non-void check and id check
  828.       require
  829.      e.result_type.run_class.running.count = 1
  830.       local
  831.      point1, point2, idx: INTEGER;
  832.      rc: RUN_CLASS;
  833.      ca: like code_attribute;
  834.       do
  835.      e.compile_to_jvm;
  836.      if run_control.no_check then
  837.         ca := code_attribute;
  838.         ca.opcode_dup;
  839.         point1 := ca.opcode_ifnull;
  840.         ca.opcode_dup;
  841.         rc := e.result_type.run_class.running.first;
  842.         idx := rc.fully_qualified_constant_pool_index;
  843.         ca.opcode_instanceof(idx);
  844.         point2 := ca.opcode_ifne;
  845.         idx := idx_bad_target(e);
  846.         ca.opcode_system_err_println(idx);
  847.         ca.opcode_aconst_null;
  848.         ca.opcode_athrow;
  849.         ca.resolve_u2_branch(point1);
  850.         idx := idx_void_target(e);
  851.         ca.opcode_system_err_println(idx);
  852.         ca.opcode_aconst_null;
  853.         ca.opcode_athrow;
  854.         ca.resolve_u2_branch(point2);
  855.         rc.jvm_check_class_invariant;
  856.      end;
  857.       end;
  858.  
  859.    idx_bad_target(e: EXPRESSION): INTEGER is
  860.       local
  861.      sp: POSITION;
  862.       do
  863.      tmp_string.copy("Bad target ");
  864.      sp := e.start_position;
  865.      if sp /= Void then
  866.         sp.append_in(tmp_string);
  867.      end;
  868.      Result := constant_pool.idx_string(tmp_string);
  869.       end;
  870.  
  871.    idx_void_target(e: EXPRESSION): INTEGER is
  872.       local
  873.      sp: POSITION;
  874.       do
  875.      tmp_string.copy("Void target ");
  876.      sp := e.start_position;
  877.      if sp /= Void then
  878.         sp.append_in(tmp_string);
  879.      end;
  880.      Result := constant_pool.idx_string(tmp_string);
  881.       end;
  882.  
  883. end -- JVM
  884.  
  885.