view src/share/vm/c1x/c1x_Compiler.cpp @ 1941:79d04223b8a5

Added caching for resolved types and resolved fields. This is crucial, because the local load elimination will lead to wrong results, if field equality (of two RiField objects with the same object and the same RiType) is not given. The caching makes sure that the default equals implementation is sufficient.
author Thomas Wuerthinger <wuerthinger@ssw.jku.at>
date Tue, 28 Dec 2010 18:33:26 +0100
parents 48bbaead8b6c
children 00bc9eaf0e24
line wrap: on
line source

/*
 * Copyright 2000-2010 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 *
 */

# include "incls/_precompiled.incl"
# include "incls/_c1x_Compiler.cpp.incl"

C1XCompiler* C1XCompiler::_instance = NULL;

C1XCompiler::C1XCompiler() {
  _initialized = false;
  assert(_instance == NULL, "only one instance allowed");
  _instance = this;
}

// Initialization
void C1XCompiler::initialize() {
  if (_initialized) return;
  CompilerThread* THREAD = CompilerThread::current();
  _initialized = true;
  TRACE_C1X_1("C1XCompiler::initialize");

  initialize_buffer_blob();
  Runtime1::initialize(THREAD->get_buffer_blob());

  JNIEnv *env = ((JavaThread *) Thread::current())->jni_environment();
  jclass klass = env->FindClass("com/sun/hotspot/c1x/VMEntriesNative");
  if (klass == NULL) {
    fatal("c1x VMEntries class not found");
  }
  env->RegisterNatives(klass, VMEntries_methods, VMEntries_methods_count());

  {
    VM_ENTRY_MARK;
    check_pending_exception("Could not register natives");
  }

  c1x_compute_offsets();

  {
    VM_ENTRY_MARK;
    HandleMark hm;
    for (int i = 0; i < Arguments::num_c1x_args(); ++i) {
      const char* arg = Arguments::c1x_args_array()[i];
      Handle option = java_lang_String::create_from_str(arg, THREAD);
      bool result = VMExits::setOption(option);
      if (!result) fatal("Invalid option for C1X!");
    }
  }
}

void C1XCompiler::initialize_buffer_blob() {

  CompilerThread* THREAD = CompilerThread::current();
  if (THREAD->get_buffer_blob() == NULL) {
    // setup CodeBuffer.  Preallocate a BufferBlob of size
    // NMethodSizeLimit plus some extra space for constants.
    int code_buffer_size = Compilation::desired_max_code_buffer_size() +
      Compilation::desired_max_constant_size();
    BufferBlob* blob = BufferBlob::create("C1X temporary CodeBuffer",
                                          code_buffer_size);
    guarantee(blob != NULL, "must create code buffer");
    THREAD->set_buffer_blob(blob);
  }
}

// Compilation entry point for methods
void C1XCompiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci) {
  initialize();
  VM_ENTRY_MARK;
  ResourceMark rm;
  HandleMark hm;

  initialize_buffer_blob();
  VmIds::initializeObjects();

  CompilerThread::current()->set_compiling(true);
  methodOop method = (methodOop) target->get_oop();
  VMExits::compileMethod(VmIds::add<methodOop>(method), VmIds::toString<Handle>(method->name(), THREAD), entry_bci);
  CompilerThread::current()->set_compiling(false);

  VmIds::cleanupLocalObjects();
}

// Print compilation timers and statistics
void C1XCompiler::print_timers() {
  TRACE_C1X_1("C1XCompiler::print_timers");
}

oop C1XCompiler::get_RiType(ciType *type, KlassHandle accessor, TRAPS) {
  if (type->is_loaded()) {
    if (type->is_primitive_type()) {
      return VMExits::createRiTypePrimitive((int) type->basic_type(), THREAD);
    }
    KlassHandle klass = (klassOop) type->get_oop();
    Handle name = VmIds::toString<Handle>(klass->name(), THREAD);
    return createHotSpotTypeResolved(klass, name, CHECK_NULL);
  } else {
    symbolOop name = ((ciKlass *) type)->name()->get_symbolOop();
    return VMExits::createRiTypeUnresolved(VmIds::toString<Handle>(name, THREAD), THREAD);
  }
}

oop C1XCompiler::get_RiField(ciField *field, ciInstanceKlass* accessor_klass, KlassHandle accessor, Bytecodes::Code byteCode, TRAPS) {
  bool will_link = field->will_link_from_vm(accessor_klass, byteCode);
  int offset = (field->holder()->is_loaded() && will_link) ? field->offset() : -1;
  Handle field_name = VmIds::toString<Handle>(field->name()->get_symbolOop(), CHECK_0);
  Handle field_holder = get_RiType(field->holder(), accessor, CHECK_0);
  Handle field_type = get_RiType(field->type(), accessor, CHECK_0);

  // TODO: implement caching
  return VMExits::createRiField(field_holder, field_name, field_type, offset, THREAD);
}

oop C1XCompiler::createHotSpotTypeResolved(KlassHandle klass, Handle name, TRAPS) {
  if (klass->c1x_mirror() != NULL) {
    return klass->c1x_mirror();
  }

  instanceKlass::cast(HotSpotTypeResolved::klass())->initialize(CHECK_NULL);
  oop obj = instanceKlass::cast(HotSpotTypeResolved::klass())->allocate_instance(CHECK_NULL);

  HotSpotTypeResolved::set_javaMirror(obj, klass->java_mirror());
  HotSpotTypeResolved::set_name(obj, name());
  HotSpotTypeResolved::set_accessFlags(obj, klass->access_flags().as_int());
  HotSpotTypeResolved::set_isInterface(obj, klass->is_interface());
  HotSpotTypeResolved::set_isInstanceClass(obj, klass->oop_is_instance());

  if (klass->oop_is_javaArray()) {
    HotSpotTypeResolved::set_isArrayClass(obj, true);
    HotSpotTypeResolved::set_componentType(obj, NULL);
  } else {
    HotSpotTypeResolved::set_isArrayClass(obj, false);
    HotSpotTypeResolved::set_componentType(obj, NULL);
    HotSpotTypeResolved::set_isInitialized(obj, instanceKlass::cast(klass())->is_initialized());
    HotSpotTypeResolved::set_instanceSize(obj, instanceKlass::cast(klass())->size_helper() * HeapWordSize);
    HotSpotTypeResolved::set_hasFinalizer(obj, klass->has_finalizer());
  }

  // TODO replace these with correct values
  HotSpotTypeResolved::set_hasSubclass(obj, false);
  HotSpotTypeResolved::set_hasFinalizableSubclass(obj, false);

  klass->set_c1x_mirror(obj);

  return obj;
}

BasicType C1XCompiler::kindToBasicType(jchar ch) {
  switch(ch) {
    case 'z': return T_BOOLEAN;
    case 'b': return T_BYTE;
    case 's': return T_SHORT;
    case 'c': return T_CHAR;
    case 'i': return T_INT;
    case 'f': return T_FLOAT;
    case 'l': return T_LONG;
    case 'd': return T_DOUBLE;
    case 'a': return T_OBJECT;
    case 'r': return T_ADDRESS;
    case '-': return T_ILLEGAL;
    default:
      fatal(err_msg("unexpected CiKind: %c", ch));
      break;
  }
}