alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (rewriter.hpp)

This example Java source code file (rewriter.hpp) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

constantpoolcacheentry\:\:_indy_resolved_references_entries, fieldref, growablearray, jvm_constant_invokedynamic, methodref, share_vm_interpreter_rewriter_hpp, stackobj, traps

The rewriter.hpp Java example source code

/*
 * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
 * 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.
 *
 * 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.
 *
 */

#ifndef SHARE_VM_INTERPRETER_REWRITER_HPP
#define SHARE_VM_INTERPRETER_REWRITER_HPP

#include "memory/allocation.hpp"
#include "runtime/handles.inline.hpp"
#include "utilities/growableArray.hpp"

// The Rewriter adds caches to the constant pool and rewrites bytecode indices
// pointing into the constant pool for better interpreter performance.

class Rewriter: public StackObj {
 private:
  instanceKlassHandle _klass;
  constantPoolHandle  _pool;
  Array<Method*>*     _methods;
  intArray            _cp_map;
  intStack            _cp_cache_map;        // for Methodref, Fieldref,
                                            // InterfaceMethodref and InvokeDynamic
  intArray            _reference_map;       // maps from cp index to resolved_refs index (or -1)
  intStack            _resolved_references_map;    // for strings, methodHandle, methodType
  intStack            _invokedynamic_references_map; // for invokedynamic resolved refs
  intArray            _method_handle_invokers;
  int                 _resolved_reference_limit;

  // For mapping invokedynamic bytecodes, which are discovered during method
  // scanning.  The invokedynamic entries are added at the end of the cpCache.
  // If there are any invokespecial/InterfaceMethodref special case bytecodes,
  // these entries are added before invokedynamic entries so that the
  // invokespecial bytecode 16 bit index doesn't overflow.
  intStack            _invokedynamic_cp_cache_map;

  // For patching.
  GrowableArray<address>* _patch_invokedynamic_bcps;
  GrowableArray<int>*     _patch_invokedynamic_refs;

  void init_maps(int length) {
    _cp_map.initialize(length, -1);
    // Choose an initial value large enough that we don't get frequent
    // calls to grow().
    _cp_cache_map.initialize(length/2);
    // Also cache resolved objects, in another different cache.
    _reference_map.initialize(length, -1);
    _resolved_references_map.initialize(length/2);
    _invokedynamic_references_map.initialize(length/2);
    _resolved_reference_limit = -1;
    _first_iteration_cp_cache_limit = -1;

    // invokedynamic specific fields
    _invokedynamic_cp_cache_map.initialize(length/4);
    _patch_invokedynamic_bcps = new GrowableArray<address>(length/4);
    _patch_invokedynamic_refs = new GrowableArray<int>(length/4);
  }

  int _first_iteration_cp_cache_limit;
  void record_map_limits() {
    // Record initial size of the two arrays generated for the CP cache
    // relative to walking the constant pool.
    _first_iteration_cp_cache_limit = _cp_cache_map.length();
    _resolved_reference_limit = _resolved_references_map.length();
  }

  int cp_cache_delta() {
    // How many cp cache entries were added since recording map limits after
    // cp cache initialization?
    assert(_first_iteration_cp_cache_limit != -1, "only valid after first iteration");
    return _cp_cache_map.length() - _first_iteration_cp_cache_limit;
  }

  int  cp_entry_to_cp_cache(int i) { assert(has_cp_cache(i), "oob"); return _cp_map[i]; }
  bool has_cp_cache(int i) { return (uint)i < (uint)_cp_map.length() && _cp_map[i] >= 0; }

  int add_map_entry(int cp_index, intArray* cp_map, intStack* cp_cache_map) {
    assert(cp_map->at(cp_index) == -1, "not twice on same cp_index");
    int cache_index = cp_cache_map->append(cp_index);
    cp_map->at_put(cp_index, cache_index);
    return cache_index;
  }

  int add_cp_cache_entry(int cp_index) {
    assert(_pool->tag_at(cp_index).value() != JVM_CONSTANT_InvokeDynamic, "use indy version");
    assert(_first_iteration_cp_cache_limit == -1, "do not add cache entries after first iteration");
    int cache_index = add_map_entry(cp_index, &_cp_map, &_cp_cache_map);
    assert(cp_entry_to_cp_cache(cp_index) == cache_index, "");
    assert(cp_cache_entry_pool_index(cache_index) == cp_index, "");
    return cache_index;
  }

  int add_invokedynamic_cp_cache_entry(int cp_index) {
    assert(_pool->tag_at(cp_index).value() == JVM_CONSTANT_InvokeDynamic, "use non-indy version");
    assert(_first_iteration_cp_cache_limit >= 0, "add indy cache entries after first iteration");
    // add to the invokedynamic index map.
    int cache_index = _invokedynamic_cp_cache_map.append(cp_index);
    // do not update _cp_map, since the mapping is one-to-many
    assert(invokedynamic_cp_cache_entry_pool_index(cache_index) == cp_index, "");
    // this index starts at one but in the bytecode it's appended to the end.
    return cache_index + _first_iteration_cp_cache_limit;
  }

  int invokedynamic_cp_cache_entry_pool_index(int cache_index) {
    int cp_index = _invokedynamic_cp_cache_map[cache_index];
    return cp_index;
  }

  // add a new CP cache entry beyond the normal cache for the special case of
  // invokespecial with InterfaceMethodref as cpool operand.
  int add_invokespecial_cp_cache_entry(int cp_index) {
    assert(_first_iteration_cp_cache_limit >= 0, "add these special cache entries after first iteration");
    // Don't add InterfaceMethodref if it already exists at the end.
    for (int i = _first_iteration_cp_cache_limit; i < _cp_cache_map.length(); i++) {
     if (cp_cache_entry_pool_index(i) == cp_index) {
       return i;
     }
    }
    int cache_index = _cp_cache_map.append(cp_index);
    assert(cache_index >= _first_iteration_cp_cache_limit, "");
    // do not update _cp_map, since the mapping is one-to-many
    assert(cp_cache_entry_pool_index(cache_index) == cp_index, "");
    return cache_index;
  }

  int  cp_entry_to_resolved_references(int cp_index) const {
    assert(has_entry_in_resolved_references(cp_index), "oob");
    return _reference_map[cp_index];
  }
  bool has_entry_in_resolved_references(int cp_index) const {
    return (uint)cp_index < (uint)_reference_map.length() && _reference_map[cp_index] >= 0;
  }

  // add a new entry to the resolved_references map
  int add_resolved_references_entry(int cp_index) {
    int ref_index = add_map_entry(cp_index, &_reference_map, &_resolved_references_map);
    assert(cp_entry_to_resolved_references(cp_index) == ref_index, "");
    return ref_index;
  }

  // add a new entries to the resolved_references map (for invokedynamic and invokehandle only)
  int add_invokedynamic_resolved_references_entries(int cp_index, int cache_index) {
    assert(_resolved_reference_limit >= 0, "must add indy refs after first iteration");
    int ref_index = -1;
    for (int entry = 0; entry < ConstantPoolCacheEntry::_indy_resolved_references_entries; entry++) {
      const int index = _resolved_references_map.append(cp_index);  // many-to-one
      assert(index >= _resolved_reference_limit, "");
      if (entry == 0) {
        ref_index = index;
      }
      assert((index - entry) == ref_index, "entries must be consecutive");
      _invokedynamic_references_map.at_put_grow(index, cache_index, -1);
    }
    return ref_index;
  }

  int resolved_references_entry_to_pool_index(int ref_index) {
    int cp_index = _resolved_references_map[ref_index];
    return cp_index;
  }

  // Access the contents of _cp_cache_map to determine CP cache layout.
  int cp_cache_entry_pool_index(int cache_index) {
    int cp_index = _cp_cache_map[cache_index];
    return cp_index;
  }

  // All the work goes in here:
  Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, Array<Method*>* methods, TRAPS);

  void compute_index_maps();
  void make_constant_pool_cache(TRAPS);
  void scan_method(Method* m, bool reverse, bool* invokespecial_error);
  void rewrite_Object_init(methodHandle m, TRAPS);
  void rewrite_member_reference(address bcp, int offset, bool reverse);
  void maybe_rewrite_invokehandle(address opc, int cp_index, int cache_index, bool reverse);
  void rewrite_invokedynamic(address bcp, int offset, bool reverse);
  void maybe_rewrite_ldc(address bcp, int offset, bool is_wide, bool reverse);
  void rewrite_invokespecial(address bcp, int offset, bool reverse, bool* invokespecial_error);

  void patch_invokedynamic_bytecodes();

  // Revert bytecodes in case of an exception.
  void restore_bytecodes();

  static methodHandle rewrite_jsrs(methodHandle m, TRAPS);
 public:
  // Driver routine:
  static void rewrite(instanceKlassHandle klass, TRAPS);
};

#endif // SHARE_VM_INTERPRETER_REWRITER_HPP

Other Java examples (source code examples)

Here is a short list of links related to this Java rewriter.hpp source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.