stackMapFrame.hpp 10.8 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
19 20 21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
22 23 24
 *
 */

25 26 27 28 29
#ifndef SHARE_VM_CLASSFILE_STACKMAPFRAME_HPP
#define SHARE_VM_CLASSFILE_STACKMAPFRAME_HPP

#include "classfile/verificationType.hpp"
#include "classfile/verifier.hpp"
30
#include "oops/method.hpp"
31 32 33 34
#include "runtime/handles.hpp"
#include "runtime/signature.hpp"
#include "utilities/exceptions.hpp"

D
duke 已提交
35 36
// A StackMapFrame represents one frame in the stack map attribute.

37 38
class TypeContext;

D
duke 已提交
39 40 41 42 43 44 45 46 47 48 49 50 51
enum {
  FLAG_THIS_UNINIT = 0x01
};

class StackMapFrame : public ResourceObj {
 private:
  int32_t _offset;

  // See comment in StackMapTable about _frame_count about why these
  // fields are int32_t instead of u2.
  int32_t _locals_size;  // number of valid type elements in _locals
  int32_t _stack_size;   // number of valid type elements in _stack

52 53 54 55
  int32_t _stack_mark;   // Records the size of the stack prior to an
                         // instruction modification, to allow rewinding
                         // when/if an error occurs.

D
duke 已提交
56 57 58 59 60 61 62 63 64
  int32_t _max_locals;
  int32_t _max_stack;

  u1 _flags;
  VerificationType* _locals; // local variable type array
  VerificationType* _stack;  // operand stack type array

  ClassVerifier* _verifier;  // the verifier verifying this method

65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
  StackMapFrame(const StackMapFrame& cp) :
      _offset(cp._offset), _locals_size(cp._locals_size),
      _stack_size(cp._stack_size), _stack_mark(cp._stack_mark),
      _max_locals(cp._max_locals), _max_stack(cp._max_stack),
      _flags(cp._flags) {
    _locals = NEW_RESOURCE_ARRAY(VerificationType, _max_locals);
    for (int i = 0; i < _max_locals; ++i) {
      if (i < _locals_size) {
        _locals[i] = cp._locals[i];
      } else {
        _locals[i] = VerificationType::bogus_type();
      }
    }
    int ss = MAX2(_stack_size, _stack_mark);
    _stack = NEW_RESOURCE_ARRAY(VerificationType, _max_stack);
    for (int i = 0; i < _max_stack; ++i) {
      if (i < ss) {
        _stack[i] = cp._stack[i];
      } else {
        _stack[i] = VerificationType::bogus_type();
      }
    }
    _verifier = NULL;
  }

D
duke 已提交
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
 public:
  // constructors

  // This constructor is used by the type checker to allocate frames
  // in type state, which have _max_locals and _max_stack array elements
  // in _locals and _stack.
  StackMapFrame(u2 max_locals, u2 max_stack, ClassVerifier* verifier);

  // This constructor is used to initialize stackmap frames in stackmap table,
  // which have _locals_size and _stack_size array elements in _locals and _stack.
  StackMapFrame(int32_t offset,
                u1 flags,
                u2 locals_size,
                u2 stack_size,
                u2 max_locals,
                u2 max_stack,
                VerificationType* locals,
                VerificationType* stack,
                ClassVerifier* v) : _offset(offset), _flags(flags),
                                    _locals_size(locals_size),
                                    _stack_size(stack_size),
111
                                    _stack_mark(-1),
D
duke 已提交
112 113 114 115 116
                                    _max_locals(max_locals),
                                    _max_stack(max_stack),
                                    _locals(locals), _stack(stack),
                                    _verifier(v) { }

117 118 119 120
  static StackMapFrame* copy(StackMapFrame* smf) {
    return new StackMapFrame(*smf);
  }

D
duke 已提交
121 122 123 124
  inline void set_offset(int32_t offset)      { _offset = offset; }
  inline void set_verifier(ClassVerifier* v)  { _verifier = v; }
  inline void set_flags(u1 flags)             { _flags = flags; }
  inline void set_locals_size(u2 locals_size) { _locals_size = locals_size; }
125
  inline void set_stack_size(u2 stack_size)   { _stack_size = _stack_mark = stack_size; }
D
duke 已提交
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
  inline void clear_stack()                   { _stack_size = 0; }
  inline int32_t offset()   const             { return _offset; }
  inline ClassVerifier* verifier() const      { return _verifier; }
  inline u1 flags() const                     { return _flags; }
  inline int32_t locals_size() const          { return _locals_size; }
  inline VerificationType* locals() const     { return _locals; }
  inline int32_t stack_size() const           { return _stack_size; }
  inline VerificationType* stack() const      { return _stack; }
  inline int32_t max_locals() const           { return _max_locals; }
  inline int32_t max_stack() const            { return _max_stack; }
  inline bool flag_this_uninit() const        { return _flags & FLAG_THIS_UNINIT; }

  // Set locals and stack types to bogus
  inline void reset() {
    int32_t i;
    for (i = 0; i < _max_locals; i++) {
      _locals[i] = VerificationType::bogus_type();
    }
    for (i = 0; i < _max_stack; i++) {
      _stack[i] = VerificationType::bogus_type();
    }
  }

  // Return a StackMapFrame with the same local variable array and empty stack.
  // Stack array is allocate with unused one element.
  StackMapFrame* frame_in_exception_handler(u1 flags);

  // Set local variable type array based on m's signature.
  VerificationType set_locals_from_arg(
    const methodHandle m, VerificationType thisKlass, TRAPS);

  // Search local variable type array and stack type array.
  // Return true if an uninitialized object is found.
  bool has_new_object() const;

  // Search local variable type array and stack type array.
  // Set every element with type of old_object to new_object.
  void initialize_object(
    VerificationType old_object, VerificationType new_object);

  // Copy local variable type array in src into this local variable type array.
  void copy_locals(const StackMapFrame* src);

  // Copy stack type array in src into this stack type array.
  void copy_stack(const StackMapFrame* src);

  // Return true if this stack map frame is assignable to target.
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
  bool is_assignable_to(
      const StackMapFrame* target, bool is_exception_handler,
      ErrorContext* ctx, TRAPS) const;

  inline void set_mark() {
#ifdef DEBUG
    // Put bogus type to indicate it's no longer valid.
    if (_stack_mark != -1) {
      for (int i = _stack_mark; i >= _stack_size; --i) {
        _stack[i] = VerificationType::bogus_type();
      }
    }
#endif // def DEBUG
    _stack_mark = _stack_size;
  }

  // Used when an error occurs and we want to reset the stack to the state
  // it was before operands were popped off.
  void restore() {
    if (_stack_mark != -1) {
      _stack_size = _stack_mark;
    }
  }
D
duke 已提交
196 197 198 199 200

  // Push type into stack type array.
  inline void push_stack(VerificationType type, TRAPS) {
    assert(!type.is_check(), "Must be a real type");
    if (_stack_size >= _max_stack) {
201 202 203
      verifier()->verify_error(
          ErrorContext::stack_overflow(_offset, this),
          "Operand stack overflow");
D
duke 已提交
204 205 206 207 208 209 210 211 212 213
      return;
    }
    _stack[_stack_size++] = type;
  }

  inline void push_stack_2(
      VerificationType type1, VerificationType type2, TRAPS) {
    assert(type1.is_long() || type1.is_double(), "must be long/double");
    assert(type2.is_long2() || type2.is_double2(), "must be long/double_2");
    if (_stack_size >= _max_stack - 1) {
214 215 216
      verifier()->verify_error(
          ErrorContext::stack_overflow(_offset, this),
          "Operand stack overflow");
D
duke 已提交
217 218 219 220 221 222 223 224 225
      return;
    }
    _stack[_stack_size++] = type1;
    _stack[_stack_size++] = type2;
  }

  // Pop and return the top type on stack without verifying.
  inline VerificationType pop_stack(TRAPS) {
    if (_stack_size <= 0) {
226 227 228
      verifier()->verify_error(
          ErrorContext::stack_underflow(_offset, this),
          "Operand stack underflow");
D
duke 已提交
229 230 231 232 233 234 235 236 237 238 239 240
      return VerificationType::bogus_type();
    }
    VerificationType top = _stack[--_stack_size];
    return top;
  }

  // Pop and return the top type on stack type array after verifying it
  // is assignable to type.
  inline VerificationType pop_stack(VerificationType type, TRAPS) {
    if (_stack_size != 0) {
      VerificationType top = _stack[_stack_size - 1];
      bool subtype = type.is_assignable_from(
241
        top, verifier(), CHECK_(VerificationType::bogus_type()));
D
duke 已提交
242
      if (subtype) {
243
        --_stack_size;
D
duke 已提交
244 245 246 247 248 249 250 251 252 253 254 255
        return top;
      }
    }
    return pop_stack_ex(type, THREAD);
  }

  inline void pop_stack_2(
      VerificationType type1, VerificationType type2, TRAPS) {
    assert(type1.is_long2() || type1.is_double2(), "must be long/double");
    assert(type2.is_long() || type2.is_double(), "must be long/double_2");
    if (_stack_size >= 2) {
      VerificationType top1 = _stack[_stack_size - 1];
256
      bool subtype1 = type1.is_assignable_from(top1, verifier(), CHECK);
D
duke 已提交
257
      VerificationType top2 = _stack[_stack_size - 2];
258
      bool subtype2 = type2.is_assignable_from(top2, verifier(), CHECK);
D
duke 已提交
259 260 261 262 263 264 265 266 267
      if (subtype1 && subtype2) {
        _stack_size -= 2;
        return;
      }
    }
    pop_stack_ex(type1, THREAD);
    pop_stack_ex(type2, THREAD);
  }

268 269 270 271 272 273 274 275
  VerificationType local_at(int index) {
    return _locals[index];
  }

  VerificationType stack_at(int index) {
    return _stack[index];
  }

D
duke 已提交
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
  // Uncommon case that throws exceptions.
  VerificationType pop_stack_ex(VerificationType type, TRAPS);

  // Return the type at index in local variable array after verifying
  // it is assignable to type.
  VerificationType get_local(int32_t index, VerificationType type, TRAPS);
  // For long/double.
  void get_local_2(
    int32_t index, VerificationType type1, VerificationType type2, TRAPS);

  // Set element at index in local variable array to type.
  void set_local(int32_t index, VerificationType type, TRAPS);
  // For long/double.
  void set_local_2(
    int32_t index, VerificationType type1, VerificationType type2, TRAPS);

  // Private auxiliary method used only in is_assignable_to(StackMapFrame).
  // Returns true if src is assignable to target.
294
  int is_assignable_to(
D
duke 已提交
295 296
    VerificationType* src, VerificationType* target, int32_t len, TRAPS) const;

297 298
  bool has_flag_match_exception(const StackMapFrame* target) const;

299 300 301
  TypeOrigin stack_top_ctx();

  void print_on(outputStream* str) const;
D
duke 已提交
302
};
303 304

#endif // SHARE_VM_CLASSFILE_STACKMAPFRAME_HPP