hotspot/src/share/vm/classfile/stackMapTable.cpp
changeset 13476 471200fb94fd
parent 9133 1c8d07466fdb
child 25505 9bd829aeb960
equal deleted inserted replaced
13475:27f1abd05ae9 13476:471200fb94fd
     1 /*
     1 /*
     2  * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    44         pre_frame, i == 0, max_locals, max_stack,
    44         pre_frame, i == 0, max_locals, max_stack,
    45         CHECK_VERIFY(pre_frame->verifier()));
    45         CHECK_VERIFY(pre_frame->verifier()));
    46       _frame_array[i] = frame;
    46       _frame_array[i] = frame;
    47       int offset = frame->offset();
    47       int offset = frame->offset();
    48       if (offset >= code_len || code_data[offset] == 0) {
    48       if (offset >= code_len || code_data[offset] == 0) {
    49         frame->verifier()->verify_error("StackMapTable error: bad offset");
    49         frame->verifier()->verify_error(
       
    50             ErrorContext::bad_stackmap(i, frame),
       
    51             "StackMapTable error: bad offset");
    50         return;
    52         return;
    51       }
    53       }
    52       pre_frame = frame;
    54       pre_frame = frame;
    53     }
    55     }
    54   }
    56   }
    66   return i;  // frame with offset doesn't exist in the array
    68   return i;  // frame with offset doesn't exist in the array
    67 }
    69 }
    68 
    70 
    69 bool StackMapTable::match_stackmap(
    71 bool StackMapTable::match_stackmap(
    70     StackMapFrame* frame, int32_t target,
    72     StackMapFrame* frame, int32_t target,
    71     bool match, bool update, TRAPS) const {
    73     bool match, bool update, ErrorContext* ctx, TRAPS) const {
    72   int index = get_index_from_offset(target);
    74   int index = get_index_from_offset(target);
    73 
    75   return match_stackmap(frame, target, index, match, update, ctx, THREAD);
    74   return match_stackmap(
       
    75     frame, target, index, match,
       
    76     update, CHECK_VERIFY_(frame->verifier(), false));
       
    77 }
    76 }
    78 
    77 
    79 // Match and/or update current_frame to the frame in stackmap table with
    78 // Match and/or update current_frame to the frame in stackmap table with
    80 // specified offset and frame index. Return true if the two frames match.
    79 // specified offset and frame index. Return true if the two frames match.
    81 //
    80 //
    86 // unconditional branch:                                 false  true
    85 // unconditional branch:                                 false  true
    87 // linear bytecode verification not following an
    86 // linear bytecode verification not following an
    88 // unconditional branch:                                 true   true
    87 // unconditional branch:                                 true   true
    89 bool StackMapTable::match_stackmap(
    88 bool StackMapTable::match_stackmap(
    90     StackMapFrame* frame, int32_t target, int32_t frame_index,
    89     StackMapFrame* frame, int32_t target, int32_t frame_index,
    91     bool match, bool update, TRAPS) const {
    90     bool match, bool update, ErrorContext* ctx, TRAPS) const {
    92   if (frame_index < 0 || frame_index >= _frame_count) {
    91   if (frame_index < 0 || frame_index >= _frame_count) {
    93     frame->verifier()->verify_error(frame->offset(),
    92     *ctx = ErrorContext::missing_stackmap(frame->offset());
    94       "Expecting a stackmap frame at branch target %d", target);
    93     frame->verifier()->verify_error(
       
    94         *ctx, "Expecting a stackmap frame at branch target %d", target);
    95     return false;
    95     return false;
    96   }
    96   }
    97 
    97 
       
    98   StackMapFrame *stackmap_frame = _frame_array[frame_index];
    98   bool result = true;
    99   bool result = true;
    99   StackMapFrame *stackmap_frame = _frame_array[frame_index];
       
   100   if (match) {
   100   if (match) {
   101     // when checking handler target, match == true && update == false
   101     // when checking handler target, match == true && update == false
   102     bool is_exception_handler = !update;
   102     bool is_exception_handler = !update;
   103     // Has direct control flow from last instruction, need to match the two
   103     // Has direct control flow from last instruction, need to match the two
   104     // frames.
   104     // frames.
   105     result = frame->is_assignable_to(
   105     result = frame->is_assignable_to(stackmap_frame, is_exception_handler,
   106       stackmap_frame, is_exception_handler,
   106         ctx, CHECK_VERIFY_(frame->verifier(), result));
   107       CHECK_VERIFY_(frame->verifier(), false));
       
   108   }
   107   }
   109   if (update) {
   108   if (update) {
   110     // Use the frame in stackmap table as current frame
   109     // Use the frame in stackmap table as current frame
   111     int lsize = stackmap_frame->locals_size();
   110     int lsize = stackmap_frame->locals_size();
   112     int ssize = stackmap_frame->stack_size();
   111     int ssize = stackmap_frame->stack_size();
   123   return result;
   122   return result;
   124 }
   123 }
   125 
   124 
   126 void StackMapTable::check_jump_target(
   125 void StackMapTable::check_jump_target(
   127     StackMapFrame* frame, int32_t target, TRAPS) const {
   126     StackMapFrame* frame, int32_t target, TRAPS) const {
       
   127   ErrorContext ctx;
   128   bool match = match_stackmap(
   128   bool match = match_stackmap(
   129     frame, target, true, false, CHECK_VERIFY(frame->verifier()));
   129     frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier()));
   130   if (!match || (target < 0 || target >= _code_length)) {
   130   if (!match || (target < 0 || target >= _code_length)) {
   131     frame->verifier()->verify_error(frame->offset(),
   131     frame->verifier()->verify_error(ctx,
   132       "Inconsistent stackmap frames at branch target %d", target);
   132         "Inconsistent stackmap frames at branch target %d", target);
   133     return;
   133     return;
   134   }
   134   }
   135   // check if uninitialized objects exist on backward branches
   135   // check if uninitialized objects exist on backward branches
   136   check_new_object(frame, target, CHECK_VERIFY(frame->verifier()));
   136   check_new_object(frame, target, CHECK_VERIFY(frame->verifier()));
   137 }
   137 }
   138 
   138 
   139 void StackMapTable::check_new_object(
   139 void StackMapTable::check_new_object(
   140     const StackMapFrame* frame, int32_t target, TRAPS) const {
   140     const StackMapFrame* frame, int32_t target, TRAPS) const {
   141   if (frame->offset() > target && frame->has_new_object()) {
   141   if (frame->offset() > target && frame->has_new_object()) {
   142     frame->verifier()->verify_error(frame->offset(),
   142     frame->verifier()->verify_error(
   143       "Uninitialized object exists on backward branch %d", target);
   143         ErrorContext::bad_code(frame->offset()),
       
   144         "Uninitialized object exists on backward branch %d", target);
   144     return;
   145     return;
   145   }
   146   }
   146 }
   147 }
   147 
   148 
   148 #ifndef PRODUCT
   149 void StackMapTable::print_on(outputStream* str) const {
   149 
   150   str->indent().print_cr("StackMapTable: frame_count = %d", _frame_count);
   150 void StackMapTable::print() const {
   151   str->indent().print_cr("table = { ");
   151   tty->print_cr("StackMapTable: frame_count = %d", _frame_count);
   152   {
   152   tty->print_cr("table = { ");
   153     streamIndentor si(str);
   153   for (int32_t i = 0; i < _frame_count; i++) {
   154     for (int32_t i = 0; i < _frame_count; ++i) {
   154     _frame_array[i]->print();
   155       _frame_array[i]->print_on(str);
   155   }
   156     }
   156   tty->print_cr(" }");
   157   }
   157 }
   158   str->print_cr(" }");
   158 
   159 }
   159 #endif
       
   160 
   160 
   161 int32_t StackMapReader::chop(
   161 int32_t StackMapReader::chop(
   162     VerificationType* locals, int32_t length, int32_t chops) {
   162     VerificationType* locals, int32_t length, int32_t chops) {
   163   if (locals == NULL) return -1;
   163   if (locals == NULL) return -1;
   164   int32_t pos = length - 1;
   164   int32_t pos = length - 1;