# HG changeset patch # User Thomas Wuerthinger # Date 1307533225 -7200 # Node ID c23d45daff9bacf61edc198c0374e63b2557bc74 # Parent 2fb8672859389830a83ea63a51370f09dd43b62b Renamed cpp/hpp file directory. diff -r 2fb867285938 -r c23d45daff9b src/share/vm/c1x/graalCodeInstaller.cpp --- a/src/share/vm/c1x/graalCodeInstaller.cpp Wed Jun 08 13:40:08 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,740 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ - -#include "precompiled.hpp" -#include "c1x/c1x_Compiler.hpp" -#include "c1x/c1x_CodeInstaller.hpp" -#include "c1x/c1x_JavaAccess.hpp" -#include "c1x/c1x_VmIds.hpp" -#include "c1/c1_Runtime1.hpp" -#include "classfile/vmSymbols.hpp" -#include "vmreg_x86.inline.hpp" - - -// TODO this should be handled in a more robust way - not hard coded... -Register CPU_REGS[] = { rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15 }; -bool OOP_ALLOWED[] = {true, true, true, true, false, false, true, true, true, true, false, true, true, true, true, true}; -const static int NUM_CPU_REGS = sizeof(CPU_REGS) / sizeof(Register); -XMMRegister XMM_REGS[] = { xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 }; -const static int NUM_XMM_REGS = sizeof(XMM_REGS) / sizeof(XMMRegister); -const static int NUM_REGS = NUM_CPU_REGS + NUM_XMM_REGS; -const static jlong NO_REF_MAP = 0x8000000000000000L; - -// convert c1x register indices (as used in oop maps) to hotspot registers -VMReg get_hotspot_reg(jint c1x_reg) { - - assert(c1x_reg >= 0 && c1x_reg < NUM_REGS, "invalid register number"); - if (c1x_reg < NUM_CPU_REGS) { - return CPU_REGS[c1x_reg]->as_VMReg(); - } else { - return XMM_REGS[c1x_reg - NUM_CPU_REGS]->as_VMReg(); - } -} - -static bool is_bit_set(oop bit_map, int i) { - const int MapWordBits = 64; - if (i < MapWordBits) { - jlong low = CiBitMap::low(bit_map); - return (low & (1LL << i)) != 0; - } else { - jint extra_idx = (i - MapWordBits) / MapWordBits; - arrayOop extra = (arrayOop) CiBitMap::extra(bit_map); - assert(extra_idx >= 0 && extra_idx < extra->length(), "unexpected index"); - jlong word = ((jlong*) extra->base(T_LONG))[extra_idx]; - return (word & (1LL << (i % MapWordBits))) != 0; - } -} - -// creates a hotspot oop map out of the byte arrays provided by CiDebugInfo -static OopMap* create_oop_map(jint frame_size, jint parameter_count, oop debug_info) { - OopMap* map = new OopMap(frame_size, parameter_count); - oop register_map = (oop) CiDebugInfo::registerRefMap(debug_info); - oop frame_map = (oop) CiDebugInfo::frameRefMap(debug_info); - - if (register_map != NULL) { - assert(CiBitMap::size(register_map) == (unsigned) NUM_CPU_REGS, "unexpected register_map length"); - for (jint i = 0; i < NUM_CPU_REGS; i++) { - bool is_oop = is_bit_set(register_map, i); - VMReg reg = get_hotspot_reg(i); - if (is_oop) { - assert(OOP_ALLOWED[i], "this register may never be an oop, register map misaligned?"); - map->set_oop(reg); - } else { - map->set_value(reg); - } - } - } - - if (frame_size > 0) { - assert(CiBitMap::size(frame_map) == frame_size / HeapWordSize, "unexpected frame_map length"); - - for (jint i = 0; i < frame_size / HeapWordSize; i++) { - bool is_oop = is_bit_set(frame_map, i); - // hotspot stack slots are 4 bytes - VMReg reg = VMRegImpl::stack2reg(i * 2); - if (is_oop) { - map->set_oop(reg); - } else { - map->set_value(reg); - } - } - } else { - assert(frame_map == NULL || CiBitMap::size(frame_map) == 0, "cannot have frame_map for frames with size 0"); - } - - return map; -} - -// TODO: finish this - c1x doesn't provide any scope values at the moment -static ScopeValue* get_hotspot_value(oop value, int frame_size) { - if (value == CiValue::IllegalValue()) { - return new LocationValue(Location::new_stk_loc(Location::invalid, 0)); - } - - BasicType type = C1XCompiler::kindToBasicType(CiKind::typeChar(CiValue::kind(value))); - Location::Type locationType = Location::normal; - if (type == T_OBJECT || type == T_ARRAY) locationType = Location::oop; - if (value->is_a(CiRegisterValue::klass())) { - jint number = CiRegister::number(CiRegisterValue::reg(value)); - if (number < 16) { - return new LocationValue(Location::new_reg_loc(locationType, as_Register(number)->as_VMReg())); - } else { - return new LocationValue(Location::new_reg_loc(locationType, as_XMMRegister(number - 16)->as_VMReg())); - } - } else if (value->is_a(CiStackSlot::klass())) { - jint index = CiStackSlot::index(value); - if (index >= 0) { - return new LocationValue(Location::new_stk_loc(locationType, index * HeapWordSize)); - } else { - int frame_size_bytes = frame_size + 2 * HeapWordSize; - return new LocationValue(Location::new_stk_loc(locationType, -(index * HeapWordSize) + frame_size_bytes)); - } - } else if (value->is_a(CiConstant::klass())){ - oop obj = CiConstant::object(value); - jlong prim = CiConstant::primitive(value); - if (type == T_INT || type == T_FLOAT || type == T_SHORT || type == T_CHAR || type == T_BOOLEAN || type == T_BYTE) { - return new ConstantIntValue(*(jint*)&prim); - } else if (type == T_LONG || type == T_DOUBLE) { - return new ConstantLongValue(prim); - } else if (type == T_OBJECT) { - oop obj = CiConstant::object(value); - if (obj == NULL) { - return new ConstantOopWriteValue(NULL); - } else { - return new ConstantOopWriteValue(JNIHandles::make_global(obj)); - } - } else if (type == T_ADDRESS) { - return new ConstantLongValue(prim); - } - tty->print("%i", type); - } else { - value->klass()->print(); - value->print(); - } - ShouldNotReachHere(); - return NULL; -} - -// constructor used to create a method -CodeInstaller::CodeInstaller(Handle target_method) { - ciMethod *ciMethodObject = NULL; - { - No_Safepoint_Verifier no_safepoint; - _env = CURRENT_ENV; - - initialize_fields(target_method); - assert(_hotspot_method != NULL && _name == NULL, "installMethod needs NON-NULL method and NULL name"); - assert(_hotspot_method->is_a(HotSpotMethodResolved::klass()), "installMethod needs a HotSpotMethodResolved"); - - methodOop method = VmIds::get(HotSpotMethodResolved::vmId(_hotspot_method)); - ciMethodObject = (ciMethod *) _env->get_object(method); - _parameter_count = method->size_of_parameters(); - } - - // (very) conservative estimate: each site needs a relocation - //CodeBuffer buffer("temp c1x method", _total_size, _sites->length() * relocInfo::length_limit); - CodeBuffer buffer(CompilerThread::current()->get_buffer_blob()); - initialize_buffer(buffer); - process_exception_handlers(); - - int stack_slots = (_frame_size / HeapWordSize) + 2; // conversion to words, need to add two slots for ret address and frame pointer - ThreadToNativeFromVM t((JavaThread*) Thread::current()); - _env->register_method(ciMethodObject, -1, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table, - &_implicit_exception_table, C1XCompiler::instance(), _env->comp_level(), false, false); - -} - -// constructor used to create a stub -CodeInstaller::CodeInstaller(Handle target_method, jlong& id) { - No_Safepoint_Verifier no_safepoint; - _env = CURRENT_ENV; - - initialize_fields(target_method); - assert(_hotspot_method == NULL && _name != NULL, "installMethod needs NON-NULL name and NULL method"); - - // (very) conservative estimate: each site needs a relocation - CodeBuffer buffer(CompilerThread::current()->get_buffer_blob()); - initialize_buffer(buffer); - - const char* cname = java_lang_String::as_utf8_string(_name); - BufferBlob* blob = BufferBlob::create(strdup(cname), &buffer); // this is leaking strings... but only a limited number of stubs will be created - IF_TRACE_C1X_3 Disassembler::decode((CodeBlob*) blob); - id = VmIds::addStub(blob->code_begin()); -} - -void CodeInstaller::initialize_fields(Handle target_method) { - _citarget_method = HotSpotTargetMethod::targetMethod(target_method); - _hotspot_method = HotSpotTargetMethod::method(target_method); - _name = HotSpotTargetMethod::name(target_method); - _sites = (arrayOop) HotSpotTargetMethod::sites(target_method); - oop assumptions = CiTargetMethod::assumptions(_citarget_method); - if (assumptions != NULL) { - _assumptions = (arrayOop) CiAssumptions::list(assumptions); - } else { - _assumptions = NULL; - } - _exception_handlers = (arrayOop) HotSpotTargetMethod::exceptionHandlers(target_method); - - _code = (arrayOop) CiTargetMethod::targetCode(_citarget_method); - _code_size = CiTargetMethod::targetCodeSize(_citarget_method); - _frame_size = CiTargetMethod::frameSize(_citarget_method); - _custom_stack_area_offset = CiTargetMethod::customStackAreaOffset(_citarget_method); - - - // (very) conservative estimate: each site needs a constant section entry - _constants_size = _sites->length() * (BytesPerLong*2); - _total_size = align_size_up(_code_size, HeapWordSize) + _constants_size; - - _next_call_type = MARK_INVOKE_INVALID; -} - -// perform data and call relocation on the CodeBuffer -void CodeInstaller::initialize_buffer(CodeBuffer& buffer) { - int locs_buffer_size = _sites->length() * (relocInfo::length_limit + sizeof(relocInfo)); - char* locs_buffer = NEW_RESOURCE_ARRAY(char, locs_buffer_size); - buffer.insts()->initialize_shared_locs((relocInfo*)locs_buffer, locs_buffer_size / sizeof(relocInfo)); - buffer.initialize_stubs_size(256); - buffer.initialize_consts_size(_constants_size); - - _oop_recorder = new OopRecorder(_env->arena()); - _env->set_oop_recorder(_oop_recorder); - _debug_recorder = new DebugInformationRecorder(_env->oop_recorder()); - _debug_recorder->set_oopmaps(new OopMapSet()); - _dependencies = new Dependencies(_env); - - _env->set_oop_recorder(_oop_recorder); - _env->set_debug_info(_debug_recorder); - _env->set_dependencies(_dependencies); - buffer.initialize_oop_recorder(_oop_recorder); - - _instructions = buffer.insts(); - _constants = buffer.consts(); - - // copy the code into the newly created CodeBuffer - memcpy(_instructions->start(), _code->base(T_BYTE), _code_size); - _instructions->set_end(_instructions->start() + _code_size); - - oop* sites = (oop*) _sites->base(T_OBJECT); - for (int i = 0; i < _sites->length(); i++) { - oop site = sites[i]; - jint pc_offset = CiTargetMethod_Site::pcOffset(site); - - if (site->is_a(CiTargetMethod_Safepoint::klass())) { - TRACE_C1X_4("safepoint at %i", pc_offset); - site_Safepoint(buffer, pc_offset, site); - } else if (site->is_a(CiTargetMethod_Call::klass())) { - TRACE_C1X_4("call at %i", pc_offset); - site_Call(buffer, pc_offset, site); - } else if (site->is_a(CiTargetMethod_DataPatch::klass())) { - TRACE_C1X_4("datapatch at %i", pc_offset); - site_DataPatch(buffer, pc_offset, site); - } else if (site->is_a(CiTargetMethod_Mark::klass())) { - TRACE_C1X_4("mark at %i", pc_offset); - site_Mark(buffer, pc_offset, site); - } else { - fatal("unexpected Site subclass"); - } - } - - - if (_assumptions != NULL) { - oop* assumptions = (oop*) _assumptions->base(T_OBJECT); - for (int i = 0; i < _assumptions->length(); ++i) { - oop assumption = assumptions[i]; - if (assumption != NULL) { - if (assumption->is_a(CiAssumptions_ConcreteSubtype::klass())) { - assumption_ConcreteSubtype(assumption); - } else if (assumption->is_a(CiAssumptions_ConcreteMethod::klass())) { - assumption_ConcreteMethod(assumption); - } else { - fatal("unexpected Assumption subclass"); - } - } - } - } -} - -void CodeInstaller::assumption_ConcreteSubtype(oop assumption) { - oop context_oop = CiAssumptions_ConcreteSubtype::context(assumption); - oop type_oop = CiAssumptions_ConcreteSubtype::subtype(assumption); - - ciKlass* context = (ciKlass*) CURRENT_ENV->get_object(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(context_oop))); - ciKlass* type = (ciKlass*) CURRENT_ENV->get_object(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type_oop))); - - _dependencies->assert_leaf_type(type); - if (context != type) { - assert(context->is_abstract(), ""); - ThreadToNativeFromVM trans(JavaThread::current()); - _dependencies->assert_abstract_with_unique_concrete_subtype(context, type); - } -} - -void CodeInstaller::assumption_ConcreteMethod(oop assumption) { - oop context_oop = CiAssumptions_ConcreteMethod::context(assumption); - oop method_oop = CiAssumptions_ConcreteMethod::method(assumption); - jlong context_oop_id = HotSpotMethodResolved::vmId(context_oop); - jlong method_oop_id = HotSpotMethodResolved::vmId(method_oop); - methodOop method = VmIds::get(method_oop_id); - methodOop context = VmIds::get(context_oop_id); - - ciMethod* m = (ciMethod*) CURRENT_ENV->get_object(method); - ciMethod* c = (ciMethod*) CURRENT_ENV->get_object(context); - ciKlass* context_klass = c->holder(); - { - ThreadToNativeFromVM trans(JavaThread::current()); - _dependencies->assert_unique_concrete_method(context_klass, m); - } -} - -void CodeInstaller::process_exception_handlers() { - // allocate some arrays for use by the collection code. - const int num_handlers = 5; - GrowableArray* bcis = new GrowableArray (num_handlers); - GrowableArray* scope_depths = new GrowableArray (num_handlers); - GrowableArray* pcos = new GrowableArray (num_handlers); - - if (_exception_handlers != NULL) { - oop* exception_handlers = (oop*) _exception_handlers->base(T_OBJECT); - for (int i = 0; i < _exception_handlers->length(); i++) { - jint pc_offset = CiTargetMethod_Site::pcOffset(exception_handlers[i]); - int start = i; - while ((i + 1) < _exception_handlers->length() && CiTargetMethod_Site::pcOffset(exception_handlers[i + 1]) == pc_offset) - i++; - - // empty the arrays - bcis->trunc_to(0); - scope_depths->trunc_to(0); - pcos->trunc_to(0); - - for (int j = start; j <= i; j++) { - oop exc = exception_handlers[j]; - jint handler_offset = CiTargetMethod_ExceptionHandler::handlerPos(exc); - jint handler_bci = CiTargetMethod_ExceptionHandler::handlerBci(exc); - jint bci = CiTargetMethod_ExceptionHandler::bci(exc); - jint scope_level = CiTargetMethod_ExceptionHandler::scopeLevel(exc); - Handle handler_type = CiTargetMethod_ExceptionHandler::exceptionType(exc); - - assert(handler_offset != -1, "must have been generated"); - - int e = bcis->find(handler_bci); - if (e >= 0 && scope_depths->at(e) == scope_level) { - // two different handlers are declared to dispatch to the same - // catch bci. During parsing we created edges for each - // handler but we really only need one. The exception handler - // table will also get unhappy if we try to declare both since - // it's nonsensical. Just skip this handler. - continue; - } - - bcis->append(handler_bci); - if (handler_bci == -1) { - // insert a wildcard handler at scope depth 0 so that the - // exception lookup logic with find it. - scope_depths->append(0); - } else { - scope_depths->append(scope_level); - } - pcos->append(handler_offset); - - // stop processing once we hit a catch any - // if (handler->is_catch_all()) { - // assert(i == handlers->length() - 1, "catch all must be last handler"); - // } - - } - _exception_handler_table.add_subtable(pc_offset, bcis, scope_depths, pcos); - } - } - -} - -void CodeInstaller::record_scope(jint pc_offset, oop code_pos) { - oop caller_pos = CiCodePos::caller(code_pos); - if (caller_pos != NULL) { - record_scope(pc_offset, caller_pos); - } - oop frame = NULL; - if (code_pos->klass()->klass_part()->name() == vmSymbols::com_sun_cri_ci_CiFrame()) { - frame = code_pos; - } - - oop hotspot_method = CiCodePos::method(code_pos); - assert(hotspot_method != NULL && hotspot_method->is_a(HotSpotMethodResolved::klass()), "unexpected hotspot method"); - methodOop method = VmIds::get(HotSpotMethodResolved::vmId(hotspot_method)); - ciMethod *cimethod = (ciMethod *) _env->get_object(method); - jint bci = CiCodePos::bci(code_pos); - bool reexecute; - if (bci == -1) { - reexecute = false; - } else { - Bytecodes::Code code = Bytecodes::java_code_at(method, method->bcp_from(bci)); - reexecute = Interpreter::bytecode_should_reexecute(code); - } - - if (TraceC1X >= 2) { - tty->print_cr("Recording scope pc_offset=%d bci=%d frame=%d", pc_offset, bci, frame); - } - - if (frame != NULL) { - jint local_count = CiFrame::numLocals(frame); - jint expression_count = CiFrame::numStack(frame); - jint monitor_count = CiFrame::numLocks(frame); - arrayOop values = (arrayOop) CiFrame::values(frame); - - assert(local_count + expression_count + monitor_count == values->length(), "unexpected values length"); - - GrowableArray* locals = new GrowableArray (); - GrowableArray* expressions = new GrowableArray (); - GrowableArray* monitors = new GrowableArray (); - - if (TraceC1X >= 2) { - tty->print_cr("Scope at bci %d with %d values", bci, values->length()); - tty->print_cr("%d locals %d expressions, %d monitors", local_count, expression_count, monitor_count); - } - - for (jint i = 0; i < values->length(); i++) { - ScopeValue* value = get_hotspot_value(((oop*) values->base(T_OBJECT))[i], _frame_size); - - if (i < local_count) { - locals->append(value); - } else if (i < local_count + expression_count) { - expressions->append(value); - } else { - assert(value->is_location(), "invalid monitor location"); - LocationValue* loc = (LocationValue*)value; - int monitor_offset = loc->location().stack_offset(); - LocationValue* obj = new LocationValue(Location::new_stk_loc(Location::oop, monitor_offset + BasicObjectLock::obj_offset_in_bytes())); - monitors->append(new MonitorValue(obj, Location::new_stk_loc(Location::normal, monitor_offset + BasicObjectLock::lock_offset_in_bytes()))); - } - } - DebugToken* locals_token = _debug_recorder->create_scope_values(locals); - DebugToken* expressions_token = _debug_recorder->create_scope_values(expressions); - DebugToken* monitors_token = _debug_recorder->create_monitor_values(monitors); - - _debug_recorder->describe_scope(pc_offset, cimethod, bci, reexecute, false, false, locals_token, expressions_token, monitors_token); - } else { - _debug_recorder->describe_scope(pc_offset, cimethod, bci, reexecute, false, false, NULL, NULL, NULL); - } -} - -void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site) { - oop debug_info = CiTargetMethod_Safepoint::debugInfo(site); - assert(debug_info != NULL, "debug info expected"); - - // address instruction = _instructions->start() + pc_offset; - // jint next_pc_offset = Assembler::locate_next_instruction(instruction) - _instructions->start(); - _debug_recorder->add_safepoint(pc_offset, create_oop_map(_frame_size, _parameter_count, debug_info)); - - oop code_pos = CiDebugInfo::codePos(debug_info); - record_scope(pc_offset, code_pos); - - _debug_recorder->end_safepoint(pc_offset); -} - -void CodeInstaller::site_Call(CodeBuffer& buffer, jint pc_offset, oop site) { - oop runtime_call = CiTargetMethod_Call::runtimeCall(site); - oop hotspot_method = CiTargetMethod_Call::method(site); - oop symbol = CiTargetMethod_Call::symbol(site); - oop global_stub = CiTargetMethod_Call::globalStubID(site); - - oop debug_info = CiTargetMethod_Call::debugInfo(site); - - assert((runtime_call ? 1 : 0) + (hotspot_method ? 1 : 0) + (symbol ? 1 : 0) + (global_stub ? 1 : 0) == 1, "Call site needs exactly one type"); - - assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size)"); - jint next_pc_offset = pc_offset + NativeCall::instruction_size; - - if (debug_info != NULL) { - _debug_recorder->add_safepoint(next_pc_offset, create_oop_map(_frame_size, _parameter_count, debug_info)); - oop code_pos = CiDebugInfo::codePos(debug_info); - record_scope(next_pc_offset, code_pos); - } - - if (runtime_call != NULL) { - NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); - if (runtime_call == CiRuntimeCall::Debug()) { - TRACE_C1X_3("CiRuntimeCall::Debug()"); - } else if (runtime_call == CiRuntimeCall::UnwindException()) { - call->set_destination(Runtime1::entry_for(Runtime1::c1x_unwind_exception_call_id)); - _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); - TRACE_C1X_3("CiRuntimeCall::UnwindException()"); - } else if (runtime_call == CiRuntimeCall::HandleException()) { - call->set_destination(Runtime1::entry_for(Runtime1::c1x_handle_exception_id)); - _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); - TRACE_C1X_3("CiRuntimeCall::HandleException()"); - } else if (runtime_call == CiRuntimeCall::JavaTimeMillis()) { - call->set_destination((address)os::javaTimeMillis); - _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); - TRACE_C1X_3("CiRuntimeCall::JavaTimeMillis()"); - } else if (runtime_call == CiRuntimeCall::JavaTimeNanos()) { - call->set_destination((address)os::javaTimeNanos); - _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); - TRACE_C1X_3("CiRuntimeCall::JavaTimeNanos()"); - } else if (runtime_call == CiRuntimeCall::ArithmeticFrem()) { - call->set_destination(Runtime1::entry_for(Runtime1::c1x_arithmetic_frem_id)); - _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); - TRACE_C1X_3("CiRuntimeCall::ArithmeticFrem()"); - } else if (runtime_call == CiRuntimeCall::ArithmeticDrem()) { - call->set_destination(Runtime1::entry_for(Runtime1::c1x_arithmetic_drem_id)); - _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); - TRACE_C1X_3("CiRuntimeCall::ArithmeticDrem()"); - } else if (runtime_call == CiRuntimeCall::RegisterFinalizer()) { - call->set_destination(Runtime1::entry_for(Runtime1::register_finalizer_id)); - _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); - } else if (runtime_call == CiRuntimeCall::Deoptimize()) { - call->set_destination(SharedRuntime::deopt_blob()->uncommon_trap()); - _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); - } else { - runtime_call->print(); - fatal("runtime_call not implemented"); - } - } else if (global_stub != NULL) { - NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset); - assert(java_lang_boxing_object::is_instance(global_stub, T_LONG), "global_stub needs to be of type Long"); - - if (inst->is_call()) { - nativeCall_at((address)inst)->set_destination(VmIds::getStub(global_stub)); - } else { - nativeJump_at((address)inst)->set_jump_destination(VmIds::getStub(global_stub)); - } - _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand); - TRACE_C1X_3("relocating (stub) at %016x", inst); - } else if (symbol != NULL) { - fatal("symbol"); - } else { // method != NULL - NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); - assert(hotspot_method != NULL, "unexpected RiMethod"); - assert(debug_info != NULL, "debug info expected"); - - methodOop method = NULL; - if (hotspot_method->is_a(HotSpotMethodResolved::klass())) method = VmIds::get(HotSpotMethodResolved::vmId(hotspot_method)); - - assert(debug_info != NULL, "debug info expected"); - - TRACE_C1X_3("method call"); - switch (_next_call_type) { - case MARK_INVOKEVIRTUAL: - case MARK_INVOKEINTERFACE: { - assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface"); - - call->set_destination(SharedRuntime::get_resolve_virtual_call_stub()); - _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc), Assembler::call32_operand); - break; - } - case MARK_INVOKESTATIC: { - assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic"); - call->set_destination(SharedRuntime::get_resolve_static_call_stub()); - _instructions->relocate(call->instruction_address(), relocInfo::static_call_type, Assembler::call32_operand); - break; - } - case MARK_INVOKESPECIAL: { - assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial"); - - call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub()); - _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type, Assembler::call32_operand); - break; - } - case MARK_INVOKE_INVALID: - default: - fatal("invalid _next_call_type value"); - break; - } - } - _next_call_type = MARK_INVOKE_INVALID; - if (debug_info != NULL) { - _debug_recorder->end_safepoint(next_pc_offset); - } -} - -void CodeInstaller::site_DataPatch(CodeBuffer& buffer, jint pc_offset, oop site) { - oop constant = CiTargetMethod_DataPatch::constant(site); - oop kind = CiConstant::kind(constant); - - address instruction = _instructions->start() + pc_offset; - - char typeChar = CiKind::typeChar(kind); - switch (typeChar) { - case 'z': - case 'b': - case 's': - case 'c': - case 'i': - fatal("int-sized values not expected in DataPatch") - ; - break; - case 'f': - case 'l': - case 'd': { - address operand = Assembler::locate_operand(instruction, Assembler::disp32_operand); - address next_instruction = Assembler::locate_next_instruction(instruction); - // we don't care if this is a long/double/etc., the primitive field contains the right bits - int size = _constants->size(); - if (typeChar == 'd' || typeChar == 'l') { - size = _constants->align_at_start(size); - } - address dest = _constants->start() + size; - _constants->set_end(dest + BytesPerLong); - *(jlong*) dest = CiConstant::primitive(constant); - - long disp = dest - next_instruction; - assert(disp == (jint) disp, "disp doesn't fit in 32 bits"); - *((jint*) operand) = (jint) disp; - - _instructions->relocate(instruction, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand); - TRACE_C1X_3("relocating (%c) at %016x/%016x with destination at %016x (%d)", typeChar, instruction, operand, dest, size); - break; - } - case 'a': { - address operand = Assembler::locate_operand(instruction, Assembler::imm_operand); - Handle obj = CiConstant::object(constant); - - if (obj->is_a(HotSpotTypeResolved::klass())) { - assert(!obj.is_null(), ""); - *((jobject*) operand) = JNIHandles::make_local(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(obj))); - _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); - TRACE_C1X_3("relocating (HotSpotType) at %016x/%016x", instruction, operand); - } else { - jobject value; - if (obj() == HotSpotProxy::DUMMY_CONSTANT_OBJ()) { - value = (jobject) Universe::non_oop_word(); - } else { - value = JNIHandles::make_local(obj()); - } - *((jobject*) operand) = value; - _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); - TRACE_C1X_3("relocating (oop constant) at %016x/%016x", instruction, operand); - } - break; - } - default: - fatal("unexpected CiKind in DataPatch"); - break; - } -} - -void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, oop site) { - oop id_obj = CiTargetMethod_Mark::id(site); - arrayOop references = (arrayOop) CiTargetMethod_Mark::references(site); - - if (id_obj != NULL) { - assert(java_lang_boxing_object::is_instance(id_obj, T_INT), "Integer id expected"); - jint id = id_obj->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT)); - - address instruction = _instructions->start() + pc_offset; - - switch (id) { - case MARK_UNVERIFIED_ENTRY: - _offsets.set_value(CodeOffsets::Entry, pc_offset); - break; - case MARK_VERIFIED_ENTRY: - _offsets.set_value(CodeOffsets::Verified_Entry, pc_offset); - break; - case MARK_OSR_ENTRY: - _offsets.set_value(CodeOffsets::OSR_Entry, pc_offset); - break; - case MARK_UNWIND_ENTRY: - _offsets.set_value(CodeOffsets::UnwindHandler, pc_offset); - break; - case MARK_EXCEPTION_HANDLER_ENTRY: - _offsets.set_value(CodeOffsets::Exceptions, pc_offset); - break; - case MARK_DEOPT_HANDLER_ENTRY: - _offsets.set_value(CodeOffsets::Deopt, pc_offset); - break; - case MARK_STATIC_CALL_STUB: { - assert(references->length() == 1, "static call stub needs one reference"); - oop ref = ((oop*) references->base(T_OBJECT))[0]; - address call_pc = _instructions->start() + CiTargetMethod_Site::pcOffset(ref); - _instructions->relocate(instruction, static_stub_Relocation::spec(call_pc)); - _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); - break; - } - case MARK_INVOKE_INVALID: - case MARK_INVOKEINTERFACE: - case MARK_INVOKESTATIC: - case MARK_INVOKESPECIAL: - case MARK_INVOKEVIRTUAL: - _next_call_type = (MarkId) id; - _invoke_mark_pc = instruction; - break; - case MARK_IMPLICIT_NULL: - _implicit_exception_table.append(pc_offset, pc_offset); - break; - case MARK_KLASS_PATCHING: - case MARK_ACCESS_FIELD_PATCHING: { - unsigned char* byte_count = (unsigned char*) (instruction - 1); - unsigned char* byte_skip = (unsigned char*) (instruction - 2); - unsigned char* being_initialized_entry_offset = (unsigned char*) (instruction - 3); - - assert(*byte_skip == 5, "unexpected byte_skip"); - - assert(references->length() == 2, "MARK_KLASS_PATCHING/MARK_ACCESS_FIELD_PATCHING needs 2 references"); - oop ref1 = ((oop*) references->base(T_OBJECT))[0]; - oop ref2 = ((oop*) references->base(T_OBJECT))[1]; - int i_byte_count = CiTargetMethod_Site::pcOffset(ref2) - CiTargetMethod_Site::pcOffset(ref1); - assert(i_byte_count == (unsigned char)i_byte_count, "invalid offset"); - *byte_count = i_byte_count; - *being_initialized_entry_offset = *byte_count + *byte_skip; - - // we need to correct the offset of a field access - it's created with MAX_INT to ensure the correct size, and hotspot expects 0 - if (id == MARK_ACCESS_FIELD_PATCHING) { - NativeMovRegMem* inst = nativeMovRegMem_at(_instructions->start() + CiTargetMethod_Site::pcOffset(ref1)); - assert(inst->offset() == max_jint, "unexpected offset value"); - inst->set_offset(0); - } - break; - } - case MARK_DUMMY_OOP_RELOCATION: { - _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); - - RelocIterator iter(_instructions, (address) instruction, (address) (instruction + 1)); - relocInfo::change_reloc_info_for_address(&iter, (address) instruction, relocInfo::oop_type, relocInfo::none); - break; - } - default: - ShouldNotReachHere(); - break; - } - } -} - diff -r 2fb867285938 -r c23d45daff9b src/share/vm/c1x/graalCodeInstaller.hpp --- a/src/share/vm/c1x/graalCodeInstaller.hpp Wed Jun 08 13:40:08 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ - -/* - * This class handles the conversion from a CiTargetMethod to a CodeBlob or an nmethod. - */ -class CodeInstaller { -private: - // these need to correspond to HotSpotXirGenerator.java - enum MarkId { - MARK_VERIFIED_ENTRY = 0x0001, - MARK_UNVERIFIED_ENTRY = 0x0002, - MARK_OSR_ENTRY = 0x0003, - MARK_UNWIND_ENTRY = 0x0004, - MARK_EXCEPTION_HANDLER_ENTRY = 0x0005, - MARK_DEOPT_HANDLER_ENTRY = 0x0006, - MARK_STATIC_CALL_STUB = 0x1000, - MARK_INVOKE_INVALID = 0x2000, - MARK_INVOKEINTERFACE = 0x2001, - MARK_INVOKESTATIC = 0x2002, - MARK_INVOKESPECIAL = 0x2003, - MARK_INVOKEVIRTUAL = 0x2004, - MARK_IMPLICIT_NULL = 0x3000, - MARK_KLASS_PATCHING = 0x4000, - MARK_DUMMY_OOP_RELOCATION = 0x4001, - MARK_ACCESS_FIELD_PATCHING = 0x4002 - }; - - ciEnv* _env; - - oop _citarget_method; - oop _hotspot_method; - oop _name; - arrayOop _sites; - arrayOop _assumptions; - arrayOop _exception_handlers; - CodeOffsets _offsets; - - arrayOop _code; - jint _code_size; - jint _frame_size; - jint _custom_stack_area_offset; - jint _parameter_count; - jint _constants_size; - jint _total_size; - - MarkId _next_call_type; - address _invoke_mark_pc; - - CodeSection* _instructions; - CodeSection* _constants; - - OopRecorder* _oop_recorder; - DebugInformationRecorder* _debug_recorder; - Dependencies* _dependencies; - ExceptionHandlerTable _exception_handler_table; - ImplicitExceptionTable _implicit_exception_table; - -public: - - // constructor used to create a method - CodeInstaller(Handle target_method); - - // constructor used to create a stub - CodeInstaller(Handle target_method, jlong& id); - -private: - // extract the fields of the CiTargetMethod - void initialize_fields(Handle target_method); - - // perform data and call relocation on the CodeBuffer - void initialize_buffer(CodeBuffer& buffer); - - void assumption_ConcreteSubtype(oop assumption); - void assumption_ConcreteMethod(oop assumption); - - void site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site); - void site_Call(CodeBuffer& buffer, jint pc_offset, oop site); - void site_DataPatch(CodeBuffer& buffer, jint pc_offset, oop site); - void site_Mark(CodeBuffer& buffer, jint pc_offset, oop site); - - void record_scope(jint pc_offset, oop code_pos); - - void process_exception_handlers(); - -}; diff -r 2fb867285938 -r c23d45daff9b src/share/vm/c1x/graalCompiler.cpp --- a/src/share/vm/c1x/graalCompiler.cpp Wed Jun 08 13:40:08 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,215 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ - -#include "precompiled.hpp" -#include "c1x/c1x_Compiler.hpp" -#include "c1x/c1x_JavaAccess.hpp" -#include "c1x/c1x_VMExits.hpp" -#include "c1x/c1x_VMEntries.hpp" -#include "c1x/c1x_VmIds.hpp" -#include "c1/c1_Runtime1.hpp" -#include "runtime/arguments.hpp" - -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"); - - VmIds::initializeObjects(); - - initialize_buffer_blob(); - Runtime1::initialize(THREAD->get_buffer_blob()); - - JNIEnv *env = ((JavaThread *) Thread::current())->jni_environment(); - jclass klass = env->FindClass("com/oracle/max/graal/runtime/VMEntriesNative"); - if (klass == NULL) { - tty->print_cr("c1x VMEntries class not found"); - vm_abort(false); - } - 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; - VMExits::setDefaultOptions(); - 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); - jboolean result = VMExits::setOption(option); - if (!result) { - tty->print_cr("Invalid option for C1X!"); - vm_abort(false); - } - } - - VMExits::initializeCompiler(); - } -} - -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(); - - TRACE_C1X_2("C1XCompiler::compile_method"); - - CompilerThread::current()->set_compiling(true); - methodOop method = (methodOop) target->get_oop(); - VMExits::compileMethod(VmIds::add(method), VmIds::toString(method->name(), THREAD), entry_bci); - CompilerThread::current()->set_compiling(false); - - VmIds::cleanupLocalObjects(); - TRACE_C1X_2("C1XCompiler::compile_method exit"); -} - -// 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(klass->name(), THREAD); - return createHotSpotTypeResolved(klass, name, CHECK_NULL); - } else { - Symbol* name = ((ciKlass *) type)->name()->get_symbol(); - return VMExits::createRiTypeUnresolved(VmIds::toString(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(field->name()->get_symbol(), CHECK_0); - Handle field_holder = get_RiType(field->holder(), accessor, CHECK_0); - Handle field_type = get_RiType(field->type(), accessor, CHECK_0); - int flags = field->flags().as_int(); - return VMExits::createRiField(field_holder, field_name, field_type, offset, flags, 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); - Handle obj = instanceKlass::cast(HotSpotTypeResolved::klass())->allocate_instance(CHECK_NULL); - assert(obj() != NULL, "must succeed in allocating instance"); - - HotSpotTypeResolved::set_compiler(obj, VMExits::compilerInstance()()); - - if (klass->oop_is_instance()) { - instanceKlass* ik = (instanceKlass*)klass()->klass_part(); - Handle full_name = java_lang_String::create_from_str(ik->signature_name(), CHECK_NULL); - HotSpotType::set_name(obj, full_name()); - } else { - HotSpotType::set_name(obj, name()); - } - - HotSpotTypeResolved::set_javaMirror(obj, klass->java_mirror()); - HotSpotTypeResolved::set_simpleName(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; - } - return T_ILLEGAL; -} - diff -r 2fb867285938 -r c23d45daff9b src/share/vm/c1x/graalCompiler.hpp --- a/src/share/vm/c1x/graalCompiler.hpp Wed Jun 08 13:40:08 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ - -#include "compiler/abstractCompiler.hpp" - -class C1XCompiler : public AbstractCompiler { - -private: - - bool _initialized; - - static C1XCompiler* _instance; - -public: - - C1XCompiler(); - - static C1XCompiler* instance() { return _instance; } - - - virtual const char* name() { return "C1X"; } - - // Native / OSR not supported - virtual bool supports_native() { return false; } - virtual bool supports_osr () { return false; } - - // Pretend to be C1 - bool is_c1 () { return true; } - bool is_c2 () { return false; } - - // Initialization - virtual void initialize(); - - // Compilation entry point for methods - virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci); - - // Print compilation timers and statistics - virtual void print_timers(); - - static oop get_RiType(ciType *klass, KlassHandle accessor, TRAPS); - static oop get_RiField(ciField *ciField, ciInstanceKlass* accessor_klass, KlassHandle accessor, Bytecodes::Code byteCode, TRAPS); - - static oop createHotSpotTypeResolved(KlassHandle klass, Handle name, TRAPS); - - static BasicType kindToBasicType(jchar ch); - - static int to_cp_index_u2(int index) { - // Swap. - index = ((index & 0xFF) << 8) | (index >> 8); - // Tag. - index = index + constantPoolOopDesc::CPCACHE_INDEX_TAG; - return index; - } - -private: - - void initialize_buffer_blob(); -}; - -// Tracing macros - -#define IF_TRACE_C1X_1 if (!(TraceC1X >= 1)) ; else -#define IF_TRACE_C1X_2 if (!(TraceC1X >= 2)) ; else -#define IF_TRACE_C1X_3 if (!(TraceC1X >= 3)) ; else -#define IF_TRACE_C1X_4 if (!(TraceC1X >= 4)) ; else -#define IF_TRACE_C1X_5 if (!(TraceC1X >= 5)) ; else - -// using commas and else to keep one-instruction semantics - -#define TRACE_C1X_1 if (!(TraceC1X >= 1 && (tty->print("TraceC1X-1: "), true))) ; else tty->print_cr -#define TRACE_C1X_2 if (!(TraceC1X >= 2 && (tty->print(" TraceC1X-2: "), true))) ; else tty->print_cr -#define TRACE_C1X_3 if (!(TraceC1X >= 3 && (tty->print(" TraceC1X-3: "), true))) ; else tty->print_cr -#define TRACE_C1X_4 if (!(TraceC1X >= 4 && (tty->print(" TraceC1X-4: "), true))) ; else tty->print_cr -#define TRACE_C1X_5 if (!(TraceC1X >= 5 && (tty->print(" TraceC1X-5: "), true))) ; else tty->print_cr - - - diff -r 2fb867285938 -r c23d45daff9b src/share/vm/c1x/graalJavaAccess.cpp --- a/src/share/vm/c1x/graalJavaAccess.cpp Wed Jun 08 13:40:08 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ - -#include "precompiled.hpp" -#include "c1x/c1x_JavaAccess.hpp" -#include "runtime/jniHandles.hpp" -#include "classfile/symbolTable.hpp" -// This function is similar to javaClasses.cpp, it computes the field offset of a (static or instance) field. -// It looks up the name and signature symbols without creating new ones, all the symbols of these classes need to be already loaded. - -static void compute_offset(int &dest_offset, klassOop klass_oop, const char* name, const char* signature, bool static_field) { - Symbol* name_symbol = SymbolTable::probe(name, (int)strlen(name)); - Symbol* signature_symbol = SymbolTable::probe(signature, (int)strlen(signature)); -#ifdef DEBUG - if (name_symbol == NULL) { - tty->print_cr("symbol with name %s was not found in symbol table (klass=%s)", name, klass_oop->klass_part()->name()->as_C_string()); - } -#endif - assert(name_symbol != NULL, "symbol not found - class layout changed?"); - assert(signature_symbol != NULL, "symbol not found - class layout changed?"); - - instanceKlass* ik = instanceKlass::cast(klass_oop); - fieldDescriptor fd; - if (!ik->find_field(name_symbol, signature_symbol, &fd)) { - ResourceMark rm; - tty->print_cr("Invalid layout of %s at %s", name_symbol->as_C_string(), ik->external_name()); - fatal("Invalid layout of preloaded class"); - } - assert(fd.is_static() == static_field, "static/instance mismatch"); - dest_offset = fd.offset(); -} - -// This piece of macro magic creates the contents of the c1x_compute_offsets method that initializes the field indices of all the access classes. - -#define START_CLASS(name) { klassOop k = SystemDictionary::name##_klass(); assert(k != NULL, "Could not find class " #name ""); - -#define END_CLASS } - -#define FIELD(klass, name, signature, static_field) compute_offset(klass::_##name##_offset, k, #name, signature, static_field); -#define CHAR_FIELD(klass, name) FIELD(klass, name, "C", false) -#define INT_FIELD(klass, name) FIELD(klass, name, "I", false) -#define BOOLEAN_FIELD(klass, name) FIELD(klass, name, "Z", false) -#define LONG_FIELD(klass, name) FIELD(klass, name, "J", false) -#define OOP_FIELD(klass, name, signature) FIELD(klass, name, signature, false) -#define STATIC_OOP_FIELD(klass, name, signature) FIELD(klass, name, signature, true) - - -void c1x_compute_offsets() { - COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, OOP_FIELD, STATIC_OOP_FIELD) -} - -#define EMPTY0 -#define EMPTY1(x) -#define EMPTY2(x,y) -#define FIELD2(klass, name) int klass::_##name##_offset = 0; -#define FIELD3(klass, name, sig) FIELD2(klass, name) - -COMPILER_CLASSES_DO(EMPTY1, EMPTY0, FIELD2, FIELD2, FIELD2, FIELD2, FIELD3, FIELD3) - - - - - diff -r 2fb867285938 -r c23d45daff9b src/share/vm/c1x/graalJavaAccess.hpp --- a/src/share/vm/c1x/graalJavaAccess.hpp Wed Jun 08 13:40:08 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,264 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ - -void c1x_compute_offsets(); - -#include "classfile/systemDictionary.hpp" -#include "oops/instanceMirrorKlass.hpp" - -/* This macro defines the structure of the CiTargetMethod - classes. - * It will generate classes with accessors similar to javaClasses.hpp, but with specializations for oops, Handles and jni handles. - * - * The public interface of these classes will look like this: - - * class CiStackSlot : AllStatic { - * public: - * static klassOop klass(); - * static jint index(oop obj); - * static jint index(Handle obj); - * static jint index(jobject obj); - * static void set_index(oop obj, jint x); - * static void set_index(Handle obj, jint x); - * static void set_index(jobject obj, jint x); - * }; - * - */ - -#define COMPILER_CLASSES_DO(start_class, end_class, char_field, int_field, boolean_field, long_field, oop_field, static_oop_field) \ - start_class(HotSpotTypeResolved) \ - oop_field(HotSpotTypeResolved, compiler, "Lcom/oracle/max/graal/runtime/Compiler;") \ - oop_field(HotSpotTypeResolved, javaMirror, "Ljava/lang/Class;") \ - oop_field(HotSpotTypeResolved, simpleName, "Ljava/lang/String;") \ - int_field(HotSpotTypeResolved, accessFlags) \ - boolean_field(HotSpotTypeResolved, hasFinalizer) \ - boolean_field(HotSpotTypeResolved, hasSubclass) \ - boolean_field(HotSpotTypeResolved, hasFinalizableSubclass) \ - boolean_field(HotSpotTypeResolved, isInitialized) \ - boolean_field(HotSpotTypeResolved, isArrayClass) \ - boolean_field(HotSpotTypeResolved, isInstanceClass) \ - boolean_field(HotSpotTypeResolved, isInterface) \ - int_field(HotSpotTypeResolved, instanceSize) \ - oop_field(HotSpotTypeResolved, componentType, "Lcom/sun/cri/ri/RiType;") \ - end_class \ - start_class(HotSpotType) \ - oop_field(HotSpotType, name, "Ljava/lang/String;") \ - end_class \ - start_class(HotSpotField) \ - oop_field(HotSpotField, constant, "Lcom/sun/cri/ci/CiConstant;") \ - end_class \ - start_class(HotSpotMethodResolved) \ - long_field(HotSpotMethodResolved, vmId) \ - end_class \ - start_class(HotSpotProxy) \ - static_oop_field(HotSpotProxy, DUMMY_CONSTANT_OBJ, "Ljava/lang/Long;") \ - end_class \ - start_class(HotSpotTargetMethod) \ - oop_field(HotSpotTargetMethod, targetMethod, "Lcom/sun/cri/ci/CiTargetMethod;") \ - oop_field(HotSpotTargetMethod, method, "Lcom/oracle/max/graal/runtime/HotSpotMethodResolved;") \ - oop_field(HotSpotTargetMethod, name, "Ljava/lang/String;") \ - oop_field(HotSpotTargetMethod, sites, "[Lcom/sun/cri/ci/CiTargetMethod$Site;") \ - oop_field(HotSpotTargetMethod, exceptionHandlers, "[Lcom/sun/cri/ci/CiTargetMethod$ExceptionHandler;") \ - end_class \ - start_class(HotSpotExceptionHandler) \ - int_field(HotSpotExceptionHandler, startBci) \ - int_field(HotSpotExceptionHandler, endBci) \ - int_field(HotSpotExceptionHandler, handlerBci) \ - int_field(HotSpotExceptionHandler, catchClassIndex) \ - oop_field(HotSpotExceptionHandler, catchClass, "Lcom/sun/cri/ri/RiType;") \ - end_class \ - start_class(CiTargetMethod) \ - int_field(CiTargetMethod, frameSize) \ - int_field(CiTargetMethod, customStackAreaOffset) \ - oop_field(CiTargetMethod, targetCode, "[B") \ - oop_field(CiTargetMethod, assumptions, "Lcom/sun/cri/ci/CiAssumptions;") \ - int_field(CiTargetMethod, targetCodeSize) \ - end_class \ - start_class(CiAssumptions) \ - oop_field(CiAssumptions, list, "[Lcom/sun/cri/ci/CiAssumptions$Assumption;") \ - end_class \ - start_class(CiAssumptions_ConcreteSubtype) \ - oop_field(CiAssumptions_ConcreteSubtype, context, "Lcom/sun/cri/ri/RiType;") \ - oop_field(CiAssumptions_ConcreteSubtype, subtype, "Lcom/sun/cri/ri/RiType;") \ - end_class \ - start_class(CiAssumptions_ConcreteMethod) \ - oop_field(CiAssumptions_ConcreteMethod, context, "Lcom/sun/cri/ri/RiMethod;") \ - oop_field(CiAssumptions_ConcreteMethod, method, "Lcom/sun/cri/ri/RiMethod;") \ - end_class \ - start_class(CiTargetMethod_Site) \ - int_field(CiTargetMethod_Site, pcOffset) \ - end_class \ - start_class(CiTargetMethod_Call) \ - oop_field(CiTargetMethod_Call, runtimeCall, "Lcom/sun/cri/ci/CiRuntimeCall;") \ - oop_field(CiTargetMethod_Call, method, "Lcom/sun/cri/ri/RiMethod;") \ - oop_field(CiTargetMethod_Call, symbol, "Ljava/lang/String;") \ - oop_field(CiTargetMethod_Call, globalStubID, "Ljava/lang/Object;") \ - oop_field(CiTargetMethod_Call, debugInfo, "Lcom/sun/cri/ci/CiDebugInfo;") \ - end_class \ - start_class(CiTargetMethod_DataPatch) \ - oop_field(CiTargetMethod_DataPatch, constant, "Lcom/sun/cri/ci/CiConstant;") \ - end_class \ - start_class(CiTargetMethod_Safepoint) \ - oop_field(CiTargetMethod_Safepoint, debugInfo, "Lcom/sun/cri/ci/CiDebugInfo;") \ - end_class \ - start_class(CiTargetMethod_ExceptionHandler) \ - int_field(CiTargetMethod_ExceptionHandler, handlerPos) \ - int_field(CiTargetMethod_ExceptionHandler, handlerBci) \ - int_field(CiTargetMethod_ExceptionHandler, bci) \ - int_field(CiTargetMethod_ExceptionHandler, scopeLevel) \ - oop_field(CiTargetMethod_ExceptionHandler, exceptionType, "Lcom/sun/cri/ri/RiType;")\ - end_class \ - start_class(CiTargetMethod_Mark) \ - oop_field(CiTargetMethod_Mark, id, "Ljava/lang/Object;") \ - oop_field(CiTargetMethod_Mark, references, "[Lcom/sun/cri/ci/CiTargetMethod$Mark;") \ - end_class \ - start_class(CiDebugInfo) \ - oop_field(CiDebugInfo, codePos, "Lcom/sun/cri/ci/CiCodePos;") \ - oop_field(CiDebugInfo, registerRefMap, "Lcom/sun/cri/ci/CiBitMap;") \ - oop_field(CiDebugInfo, frameRefMap, "Lcom/sun/cri/ci/CiBitMap;") \ - end_class \ - start_class(CiBitMap) \ - int_field(CiBitMap, size) \ - long_field(CiBitMap, low) \ - oop_field(CiBitMap, extra, "[J") \ - end_class \ - start_class(CiFrame) \ - oop_field(CiFrame, values, "[Lcom/sun/cri/ci/CiValue;") \ - int_field(CiFrame, numLocals) \ - int_field(CiFrame, numStack) \ - int_field(CiFrame, numLocks) \ - end_class \ - start_class(CiCodePos) \ - oop_field(CiCodePos, caller, "Lcom/sun/cri/ci/CiCodePos;") \ - oop_field(CiCodePos, method, "Lcom/sun/cri/ri/RiMethod;") \ - int_field(CiCodePos, bci) \ - end_class \ - start_class(CiConstant) \ - oop_field(CiConstant, kind, "Lcom/sun/cri/ci/CiKind;") \ - oop_field(CiConstant, object, "Ljava/lang/Object;") \ - long_field(CiConstant, primitive) \ - end_class \ - start_class(CiKind) \ - char_field(CiKind, typeChar) \ - static_oop_field(CiKind, Boolean, "Lcom/sun/cri/ci/CiKind;"); \ - static_oop_field(CiKind, Byte, "Lcom/sun/cri/ci/CiKind;"); \ - static_oop_field(CiKind, Char, "Lcom/sun/cri/ci/CiKind;"); \ - static_oop_field(CiKind, Short, "Lcom/sun/cri/ci/CiKind;"); \ - static_oop_field(CiKind, Int, "Lcom/sun/cri/ci/CiKind;"); \ - static_oop_field(CiKind, Long, "Lcom/sun/cri/ci/CiKind;"); \ - end_class \ - start_class(CiRuntimeCall) \ - static_oop_field(CiRuntimeCall, UnwindException, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ - static_oop_field(CiRuntimeCall, RegisterFinalizer, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ - static_oop_field(CiRuntimeCall, HandleException, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ - static_oop_field(CiRuntimeCall, OSRMigrationEnd, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ - static_oop_field(CiRuntimeCall, JavaTimeMillis, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ - static_oop_field(CiRuntimeCall, JavaTimeNanos, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ - static_oop_field(CiRuntimeCall, Debug, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ - static_oop_field(CiRuntimeCall, ArithmethicLrem, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ - static_oop_field(CiRuntimeCall, ArithmeticLdiv, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ - static_oop_field(CiRuntimeCall, ArithmeticFrem, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ - static_oop_field(CiRuntimeCall, ArithmeticDrem, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ - static_oop_field(CiRuntimeCall, ArithmeticCos, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ - static_oop_field(CiRuntimeCall, ArithmeticTan, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ - static_oop_field(CiRuntimeCall, ArithmeticLog, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ - static_oop_field(CiRuntimeCall, ArithmeticLog10, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ - static_oop_field(CiRuntimeCall, ArithmeticSin, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ - static_oop_field(CiRuntimeCall, Deoptimize, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ - end_class \ - start_class(RiMethod) \ - end_class \ - start_class(CiValue) \ - oop_field(CiValue, kind, "Lcom/sun/cri/ci/CiKind;") \ - static_oop_field(CiValue, IllegalValue, "Lcom/sun/cri/ci/CiValue;"); \ - end_class \ - start_class(CiRegisterValue) \ - oop_field(CiRegisterValue, reg, "Lcom/sun/cri/ci/CiRegister;") \ - end_class \ - start_class(CiRegister) \ - int_field(CiRegister, number) \ - end_class \ - start_class(CiStackSlot) \ - int_field(CiStackSlot, index) \ - end_class \ - /* end*/ - - - - -#define START_CLASS(name) \ - class name : AllStatic { \ - private: \ - friend class C1XCompiler; \ - static void check(oop obj) { assert(obj != NULL, "NULL field access of class " #name); assert(obj->is_a(SystemDictionary::name##_klass()), "wrong class, " #name " expected"); } \ - static void compute_offsets(); \ - public: \ - static klassOop klass() { return SystemDictionary::name##_klass(); } - -#define END_CLASS }; - -#define FIELD(name, type, accessor) \ - static int _##name##_offset; \ - static type name(oop obj) { check(obj); return obj->accessor(_##name##_offset); } \ - static type name(Handle obj) { check(obj()); return obj->accessor(_##name##_offset); } \ - static type name(jobject obj) { check(JNIHandles::resolve(obj)); return JNIHandles::resolve(obj)->accessor(_##name##_offset); } \ - static void set_##name(oop obj, type x) { check(obj); obj->accessor##_put(_##name##_offset, x); } \ - static void set_##name(Handle obj, type x) { check(obj()); obj->accessor##_put(_##name##_offset, x); } \ - static void set_##name(jobject obj, type x) { check(JNIHandles::resolve(obj)); JNIHandles::resolve(obj)->accessor##_put(_##name##_offset, x); } - -#define CHAR_FIELD(klass, name) FIELD(name, jchar, char_field) -#define INT_FIELD(klass, name) FIELD(name, jint, int_field) -#define BOOLEAN_FIELD(klass, name) FIELD(name, jboolean, bool_field) -#define LONG_FIELD(klass, name) FIELD(name, jlong, long_field) -#define OOP_FIELD(klass, name, signature) FIELD(name, oop, obj_field) -#define STATIC_OOP_FIELD(klassName, name, signature) \ - static int _##name##_offset; \ - static oop name() { \ - instanceKlass* ik = instanceKlass::cast(klassName::klass()); \ - address addr = ik->static_field_addr(_##name##_offset - instanceMirrorKlass::offset_of_static_fields()); \ - if (UseCompressedOops) { \ - return oopDesc::load_decode_heap_oop((narrowOop *)addr); \ - } else { \ - return oopDesc::load_decode_heap_oop((oop*)addr); \ - } \ - } \ - static void set_##name(oop x) { \ - instanceKlass* ik = instanceKlass::cast(klassName::klass()); \ - address addr = ik->static_field_addr(_##name##_offset - instanceMirrorKlass::offset_of_static_fields()); \ - if (UseCompressedOops) { \ - oopDesc::encode_store_heap_oop((narrowOop *)addr, x); \ - } else { \ - oopDesc::encode_store_heap_oop((oop*)addr, x); \ - } \ - } -COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, OOP_FIELD, STATIC_OOP_FIELD) -#undef START_CLASS -#undef END_CLASS -#undef FIELD -#undef CHAR_FIELD -#undef INT_FIELD -#undef BOOLEAN_FIELD -#undef LONG_FIELD -#undef OOP_FIELD -#undef STATIC_OOP_FIELD - - diff -r 2fb867285938 -r c23d45daff9b src/share/vm/c1x/graalVMEntries.cpp --- a/src/share/vm/c1x/graalVMEntries.cpp Wed Jun 08 13:40:08 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,710 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ - -#include "precompiled.hpp" -#include "c1x/c1x_VMEntries.hpp" -#include "c1x/c1x_Compiler.hpp" -#include "c1x/c1x_JavaAccess.hpp" -#include "c1x/c1x_CodeInstaller.hpp" -#include "c1x/c1x_VMExits.hpp" -#include "c1x/c1x_VmIds.hpp" -#include "c1/c1_Runtime1.hpp" -#include "memory/oopFactory.hpp" - -// public byte[] RiMethod_code(long vmId); -JNIEXPORT jbyteArray JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1code(JNIEnv *env, jobject, jlong vmId) { - TRACE_C1X_3("VMEntries::RiMethod_code"); - methodHandle method = VmIds::get(vmId); - int code_size = method->code_size(); - jbyteArray result = env->NewByteArray(code_size); - env->SetByteArrayRegion(result, 0, code_size, (const jbyte *) method->code_base()); - return result; -} - -// public int RiMethod_maxStackSize(long vmId); -JNIEXPORT jint JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1maxStackSize(JNIEnv *, jobject, jlong vmId) { - TRACE_C1X_3("VMEntries::RiMethod_maxStackSize"); - return VmIds::get(vmId)->max_stack(); -} - -// public int RiMethod_maxLocals(long vmId); -JNIEXPORT jint JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1maxLocals(JNIEnv *, jobject, jlong vmId) { - TRACE_C1X_3("VMEntries::RiMethod_maxLocals"); - return VmIds::get(vmId)->max_locals(); -} - -// public RiType RiMethod_holder(long vmId); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1holder(JNIEnv *, jobject, jlong vmId) { - TRACE_C1X_3("VMEntries::RiMethod_holder"); - VM_ENTRY_MARK - KlassHandle klass = VmIds::get(vmId)->method_holder(); - Handle name = VmIds::toString(klass->name(), CHECK_NULL); - oop holder = C1XCompiler::createHotSpotTypeResolved(klass, name, CHECK_NULL); - return JNIHandles::make_local(THREAD, holder); -} - -// public String RiMethod_signature(long vmId); -JNIEXPORT jstring JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1signature(JNIEnv *env, jobject, jlong vmId) { - TRACE_C1X_3("VMEntries::RiMethod_signature"); - VM_ENTRY_MARK - methodOop method = VmIds::get(vmId); - return VmIds::toString(method->signature(), THREAD); -} - -// public int RiMethod_accessFlags(long vmId); -JNIEXPORT jint JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1accessFlags(JNIEnv *, jobject, jlong vmId) { - TRACE_C1X_3("VMEntries::RiMethod_accessFlags"); - return VmIds::get(vmId)->access_flags().as_int(); -} - -// public RiExceptionHandler[] RiMethod_exceptionHandlers(long vmId); -JNIEXPORT jobjectArray JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1exceptionHandlers(JNIEnv *, jobject, jlong vmId) { - TRACE_C1X_3("VMEntries::RiMethod_exceptionHandlers"); - VM_ENTRY_MARK - methodHandle method = VmIds::get(vmId); - typeArrayHandle handlers = method->exception_table(); - int handler_count = handlers.is_null() ? 0 : handlers->length() / 4; - - instanceKlass::cast(HotSpotExceptionHandler::klass())->initialize(CHECK_NULL); - objArrayHandle array = oopFactory::new_objArray(SystemDictionary::RiExceptionHandler_klass(), handler_count, CHECK_NULL); - - for (int i = 0; i < handler_count; i++) { - // exception handlers are stored as four integers: start bci, end bci, handler bci, catch class constant pool index - int base = i * 4; - Handle entry = instanceKlass::cast(HotSpotExceptionHandler::klass())->allocate_instance(CHECK_NULL); - HotSpotExceptionHandler::set_startBci(entry, handlers->int_at(base + 0)); - HotSpotExceptionHandler::set_endBci(entry, handlers->int_at(base + 1)); - HotSpotExceptionHandler::set_handlerBci(entry, handlers->int_at(base + 2)); - int catch_class_index = handlers->int_at(base + 3); - HotSpotExceptionHandler::set_catchClassIndex(entry, catch_class_index); - - if (catch_class_index == 0) { - HotSpotExceptionHandler::set_catchClass(entry, NULL); - } else { - constantPoolOop cp = instanceKlass::cast(method->method_holder())->constants(); - ciInstanceKlass* loading_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(method->method_holder()); - bool is_accessible = false; - ciKlass *klass = CURRENT_ENV->get_klass_by_index(cp, catch_class_index, is_accessible, loading_klass); - oop catch_class = C1XCompiler::get_RiType(klass, method->method_holder(), CHECK_NULL); - - HotSpotExceptionHandler::set_catchClass(entry, catch_class); - } - array->obj_at_put(i, entry()); - } - - return (jobjectArray) JNIHandles::make_local(array()); -} - -// public boolean RiMethod_hasBalancedMonitors(long vmId); -JNIEXPORT jint JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1hasBalancedMonitors(JNIEnv *, jobject, jlong vmId) { - TRACE_C1X_3("VMEntries::RiMethod_hasBalancedMonitors"); - ciMethod* cimethod; - { - VM_ENTRY_MARK; - cimethod = (ciMethod*)CURRENT_ENV->get_object(VmIds::get(vmId)); - } - return cimethod->has_balanced_monitors(); -} - -// public boolean RiMethod_uniqueConcreteMethod(long vmId); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1uniqueConcreteMethod(JNIEnv *, jobject, jlong vmId) { - TRACE_C1X_3("VMEntries::RiMethod_uniqueConcreteMethod"); - VM_ENTRY_MARK; - ciMethod* cimethod = (ciMethod*)CURRENT_ENV->get_object(VmIds::get(vmId)); - if (cimethod->holder()->is_interface()) { - // Cannot trust interfaces. Because of: - // interface I { void foo(); } - // class A { public void foo() {} } - // class B extends A implements I { } - // class C extends B { public void foo() { } } - // class D extends B { } - // Would lead to identify C.foo() as the unique concrete method for I.foo() without seeing A.foo(). - return false; - } - klassOop klass = (klassOop)cimethod->holder()->get_oop(); - methodHandle method((methodOop)cimethod->get_oop()); - methodHandle unique_concrete; - { - ResourceMark rm; - MutexLocker locker(Compile_lock); - unique_concrete = methodHandle(Dependencies::find_unique_concrete_method(klass, method())); - } - if (unique_concrete.is_null()) { - return NULL; - } - - Handle name = VmIds::toString(unique_concrete->name(), CHECK_NULL); - oop method_resolved = VMExits::createRiMethodResolved(VmIds::add(unique_concrete()), name, CHECK_NULL); - return JNIHandles::make_local(THREAD, method_resolved); -} - -// public RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiSignature_1lookupType(JNIEnv *env, jobject, jstring jname, jobject accessingClass) { - TRACE_C1X_3("VMEntries::RiSignature_lookupType"); - VM_ENTRY_MARK; - - Symbol* nameSymbol = VmIds::toSymbol(jname); - Handle name = JNIHandles::resolve(jname); - - oop result; - if (nameSymbol == vmSymbols::int_signature()) { - result = VMExits::createRiTypePrimitive((int) T_INT, THREAD); - } else if (nameSymbol == vmSymbols::long_signature()) { - result = VMExits::createRiTypePrimitive((int) T_LONG, THREAD); - } else if (nameSymbol == vmSymbols::bool_signature()) { - result = VMExits::createRiTypePrimitive((int) T_BOOLEAN, THREAD); - } else if (nameSymbol == vmSymbols::char_signature()) { - result = VMExits::createRiTypePrimitive((int) T_CHAR, THREAD); - } else if (nameSymbol == vmSymbols::short_signature()) { - result = VMExits::createRiTypePrimitive((int) T_SHORT, THREAD); - } else if (nameSymbol == vmSymbols::byte_signature()) { - result = VMExits::createRiTypePrimitive((int) T_BYTE, THREAD); - } else if (nameSymbol == vmSymbols::double_signature()) { - result = VMExits::createRiTypePrimitive((int) T_DOUBLE, THREAD); - } else if (nameSymbol == vmSymbols::float_signature()) { - result = VMExits::createRiTypePrimitive((int) T_FLOAT, THREAD); - } else { - klassOop resolved_type = NULL; - // if the name isn't in the symbol table then the class isn't loaded anyway... - if (nameSymbol != NULL) { - Handle classloader; - Handle protectionDomain; - if (JNIHandles::resolve(accessingClass) != NULL) { - classloader = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(accessingClass))->klass_part()->class_loader(); - protectionDomain = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(accessingClass))->klass_part()->protection_domain(); - } - resolved_type = SystemDictionary::resolve_or_null(nameSymbol, classloader, protectionDomain, THREAD); - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - resolved_type = NULL; - } - } - if (resolved_type != NULL) { - result = C1XCompiler::createHotSpotTypeResolved(resolved_type, name, CHECK_NULL); - } else { - result = VMExits::createRiTypeUnresolved(name, THREAD); - } - } - - return JNIHandles::make_local(THREAD, result); -} - -// public Object RiConstantPool_lookupConstant(long vmId, int cpi); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupConstant(JNIEnv *env, jobject, jlong vmId, jint index) { - TRACE_C1X_3("VMEntries::RiConstantPool_lookupConstant"); - VM_ENTRY_MARK; - - constantPoolOop cp = VmIds::get(vmId); - - oop result = NULL; - constantTag tag = cp->tag_at(index); - if (tag.is_int()) { - result = VMExits::createCiConstant(CiKind::Int(), cp->int_at(index), CHECK_0); - } else if (tag.is_long()) { - result = VMExits::createCiConstant(CiKind::Long(), cp->long_at(index), CHECK_0); - } else if (tag.is_float()) { - result = VMExits::createCiConstantFloat(cp->float_at(index), CHECK_0); - } else if (tag.is_double()) { - result = VMExits::createCiConstantDouble(cp->double_at(index), CHECK_0); - } else if (tag.is_string() || tag.is_unresolved_string()) { - oop string = NULL; - if (cp->is_pseudo_string_at(index)) { - string = cp->pseudo_string_at(index); - } else { - string = cp->string_at(index, THREAD); - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - // TODO: Gracefully exit compilation. - fatal("out of memory during compilation!"); - return NULL; - } - } - result = VMExits::createCiConstantObject(string, CHECK_0); - } else if (tag.is_klass() || tag.is_unresolved_klass()) { - bool ignore; - ciInstanceKlass* accessor = (ciInstanceKlass*) ciEnv::current()->get_object(cp->pool_holder()); - ciKlass* klass = ciEnv::current()->get_klass_by_index(cp, index, ignore, accessor); - result = C1XCompiler::get_RiType(klass, cp->pool_holder(), CHECK_NULL); - } else if (tag.is_object()) { - oop obj = cp->object_at(index); - assert(obj->is_instance(), "must be an instance"); - result = VMExits::createCiConstantObject(obj, CHECK_NULL); - } else { - ShouldNotReachHere(); - } - - return JNIHandles::make_local(THREAD, result); -} - -// public RiMethod RiConstantPool_lookupMethod(long vmId, int cpi, byte byteCode); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupMethod(JNIEnv *env, jobject, jlong vmId, jint index, jbyte byteCode) { - TRACE_C1X_3("VMEntries::RiConstantPool_lookupMethod"); - VM_ENTRY_MARK; - - index = C1XCompiler::to_cp_index_u2(index); - constantPoolHandle cp = VmIds::get(vmId); - - Bytecodes::Code bc = (Bytecodes::Code) (((int) byteCode) & 0xFF); - ciInstanceKlass* loading_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(cp->pool_holder()); - ciMethod *cimethod = CURRENT_ENV->get_method_by_index(cp, index, bc, loading_klass); - if (cimethod->is_loaded()) { - methodOop method = (methodOop) cimethod->get_oop(); - Handle name = VmIds::toString(method->name(), CHECK_NULL); - return JNIHandles::make_local(THREAD, VMExits::createRiMethodResolved(VmIds::add(method), name, THREAD)); - } else { - Handle name = VmIds::toString(cimethod->name()->get_symbol(), CHECK_NULL); - Handle signature = VmIds::toString(cimethod->signature()->as_symbol()->get_symbol(), CHECK_NULL); - Handle holder = C1XCompiler::get_RiType(cimethod->holder(), cp->klass(), THREAD); - return JNIHandles::make_local(THREAD, VMExits::createRiMethodUnresolved(name, signature, holder, THREAD)); - } -} - -// public RiSignature RiConstantPool_lookupSignature(long vmId, int cpi); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupSignature(JNIEnv *env, jobject, jlong vmId, jint index) { - fatal("currently unsupported"); - return NULL; -} - -// public RiType RiConstantPool_lookupType(long vmId, int cpi); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupType(JNIEnv *env, jobject, jlong vmId, jint index) { - TRACE_C1X_3("VMEntries::RiConstantPool_lookupType"); - VM_ENTRY_MARK; - - constantPoolOop cp = VmIds::get(vmId); - - ciInstanceKlass* loading_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(cp->pool_holder()); - bool is_accessible = false; - ciKlass *klass = CURRENT_ENV->get_klass_by_index(cp, index, is_accessible, loading_klass); - return JNIHandles::make_local(THREAD, C1XCompiler::get_RiType(klass, cp->klass(), THREAD)); -} - -// public RiField RiConstantPool_lookupField(long vmId, int cpi); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupField(JNIEnv *env, jobject, jlong vmId, jint index, jbyte byteCode) { - TRACE_C1X_3("VMEntries::RiConstantPool_lookupField"); - VM_ENTRY_MARK; - - index = C1XCompiler::to_cp_index_u2(index); - constantPoolOop cp = VmIds::get(vmId); - - ciInstanceKlass* loading_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(cp->pool_holder()); - ciField *field = CURRENT_ENV->get_field_by_index(loading_klass, index); - - Bytecodes::Code code = (Bytecodes::Code)(((int) byteCode) & 0xFF); - Handle field_handle = C1XCompiler::get_RiField(field, loading_klass, cp->pool_holder(), code, THREAD); - bool is_constant = field->is_constant(); - if (is_constant && field->is_static()) { - ciConstant constant = field->constant_value(); - oop constant_object = NULL; - switch (constant.basic_type()) { - case T_OBJECT: - case T_ARRAY: - { - ciObject* obj = constant.as_object(); - if (obj->is_null_object()) { - constant_object = VMExits::createCiConstantObject(NULL, CHECK_0); - } else if (obj->can_be_constant()) { - constant_object = VMExits::createCiConstantObject(constant.as_object()->get_oop(), CHECK_0); - } - } - break; - case T_DOUBLE: - constant_object = VMExits::createCiConstantDouble(constant.as_double(), CHECK_0); - break; - case T_FLOAT: - constant_object = VMExits::createCiConstantFloat(constant.as_float(), CHECK_0); - break; - case T_LONG: - constant_object = VMExits::createCiConstant(CiKind::Long(), constant.as_long(), CHECK_0); - break; - case T_INT: - constant_object = VMExits::createCiConstant(CiKind::Int(), constant.as_int(), CHECK_0); - break; - case T_SHORT: - constant_object = VMExits::createCiConstant(CiKind::Short(), constant.as_int(), CHECK_0); - break; - case T_CHAR: - constant_object = VMExits::createCiConstant(CiKind::Char(), constant.as_int(), CHECK_0); - break; - case T_BYTE: - constant_object = VMExits::createCiConstant(CiKind::Byte(), constant.as_int(), CHECK_0); - break; - case T_BOOLEAN: - constant_object = VMExits::createCiConstant(CiKind::Boolean(), constant.as_int(), CHECK_0); - break; - default: - constant.print(); - fatal("Unhandled constant"); - } - if (constant_object != NULL) { - HotSpotField::set_constant(field_handle, constant_object); - } - } - return JNIHandles::make_local(THREAD, field_handle()); -} - -// public RiConstantPool RiType_constantPool(HotSpotTypeResolved klass); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_1constantPool(JNIEnv *, jobject, jobject klass) { - TRACE_C1X_3("VMEntries::RiType_constantPool"); - VM_ENTRY_MARK; - - assert(JNIHandles::resolve(klass) != NULL, ""); - constantPoolOop constantPool = ((instanceKlass*)java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))->klass_part())->constants(); - return JNIHandles::make_local(VMExits::createRiConstantPool(VmIds::add(constantPool), THREAD)); -} - -// public RiMethod RiType_resolveMethodImpl(HotSpotTypeResolved klass, String name, String signature); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_3resolveMethodImpl(JNIEnv *, jobject, jobject resolved_type, jstring name, jstring signature) { - TRACE_C1X_3("VMEntries::RiType_resolveMethodImpl"); - VM_ENTRY_MARK; - - assert(JNIHandles::resolve(resolved_type) != NULL, ""); - klassOop klass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(resolved_type)); - Symbol* name_symbol = VmIds::toSymbol(name); - Symbol* signature_symbol = VmIds::toSymbol(signature); - methodOop method = klass->klass_part()->lookup_method(name_symbol, signature_symbol); - if (method == NULL) { - if (TraceC1X >= 3) { - ResourceMark rm; - tty->print_cr("Could not resolve method %s %s on klass %s", name_symbol->as_C_string(), signature_symbol->as_C_string(), klass->klass_part()->name()->as_C_string()); - } - return NULL; - } - return JNIHandles::make_local(THREAD, VMExits::createRiMethodResolved(VmIds::add(method), Handle(JNIHandles::resolve(name)), THREAD)); -} - -// public boolean RiType_isSubtypeOf(HotSpotTypeResolved klass, RiType other); -JNIEXPORT jboolean JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_2isSubtypeOf(JNIEnv *, jobject, jobject klass, jobject jother) { - TRACE_C1X_3("VMEntries::RiType_isSubtypeOf"); - oop other = JNIHandles::resolve(jother); - assert(other->is_a(HotSpotTypeResolved::klass()), "resolved hotspot type expected"); - assert(JNIHandles::resolve(klass) != NULL, ""); - klassOop thisKlass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)); - klassOop otherKlass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(other)); - if (thisKlass->klass_part()->oop_is_instance_slow()) { - return instanceKlass::cast(thisKlass)->is_subtype_of(otherKlass); - } else if (thisKlass->klass_part()->oop_is_array()) { - return arrayKlass::cast(thisKlass)->is_subtype_of(otherKlass); - } else { - fatal("unexpected class type"); - return false; - } -} - -// public RiType RiType_componentType(HotSpotResolvedType klass); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_1componentType(JNIEnv *, jobject, jobject klass) { - TRACE_C1X_3("VMEntries::RiType_componentType"); - ciArrayKlass* array_klass; - { - VM_ENTRY_MARK; - assert(JNIHandles::resolve(klass) != NULL, ""); - array_klass = (ciArrayKlass *) CURRENT_ENV->get_object(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))); - } - ciType* element_type = array_klass->element_type(); - - VM_ENTRY_MARK; - assert(JNIHandles::resolve(klass) != NULL, ""); - return JNIHandles::make_local(C1XCompiler::get_RiType(element_type, java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)), THREAD)); -} - -// public RiType RiType_superType(HotSpotResolvedType klass); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_1superType(JNIEnv *, jobject, jobject klass) { - TRACE_C1X_3("VMEntries::RiType_superType"); - VM_ENTRY_MARK; - KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))); - ciInstanceKlass* k = NULL; - - if (klass_handle->oop_is_array()) { - k = (ciInstanceKlass *) CURRENT_ENV->get_object(SystemDictionary::Object_klass()); - } else { - guarantee(klass_handle->oop_is_instance(), "must be instance klass"); - k = (ciInstanceKlass *) CURRENT_ENV->get_object(klass_handle()); - k = k->super(); - } - - if (k != NULL) { - return JNIHandles::make_local(C1XCompiler::get_RiType(k, klass_handle, THREAD)); - } else { - return NULL; - } -} - -// public RiType RiType_uniqueConcreteSubtype(HotSpotResolvedType klass); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_1uniqueConcreteSubtype(JNIEnv *, jobject, jobject klass) { - TRACE_C1X_3("VMEntries::RiType_uniqueConcreteSubtype"); - Thread* THREAD = Thread::current(); - KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))); - ciInstanceKlass* k = NULL; - { - VM_ENTRY_MARK; - k = (ciInstanceKlass *) CURRENT_ENV->get_object(klass_handle()); - } - - if (k->is_abstract()) { - ciInstanceKlass* sub = k->unique_concrete_subklass(); - if (sub != NULL && sub->is_leaf_type()) { - VM_ENTRY_MARK; - return JNIHandles::make_local(C1XCompiler::get_RiType(sub, klass_handle, THREAD)); - } - } else if (k->is_leaf_type()) { - assert(!k->is_interface(), ""); - return klass; - } - - return NULL; -} - -// public RiType RiType_arrayOf(HotSpotTypeResolved klass); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_1arrayOf(JNIEnv *, jobject, jobject klass) { - TRACE_C1X_3("VMEntries::RiType_arrayOf"); - VM_ENTRY_MARK; - - KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))); - KlassHandle array = klass_handle->array_klass(THREAD); - Handle name = VmIds::toString(array->name(), CHECK_NULL); - return JNIHandles::make_local(THREAD, C1XCompiler::createHotSpotTypeResolved(array, name, THREAD)); -} - -// public RiType getPrimitiveArrayType(CiKind kind); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_getPrimitiveArrayType(JNIEnv *env, jobject, jobject kind) { - TRACE_C1X_3("VMEntries::VMEntries_getPrimitiveArrayType"); - VM_ENTRY_MARK; - BasicType type = C1XCompiler::kindToBasicType(CiKind::typeChar(kind)); - assert(type != T_OBJECT, "primitive type expecteds"); - ciKlass* klass = ciTypeArrayKlass::make(type); - return JNIHandles::make_local(THREAD, C1XCompiler::get_RiType(klass, KlassHandle(), THREAD)); -} - -// public RiType getType(Class javaClass); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_getType(JNIEnv *env, jobject, jobject javaClass) { - TRACE_C1X_3("VMEntries::VMEntries_getType"); - VM_ENTRY_MARK; - oop javaClassOop = JNIHandles::resolve(javaClass); - if (javaClassOop == NULL) { - fatal("argument to VMEntries.getType must not be NULL"); - return NULL; - } else if (java_lang_Class::is_primitive(javaClassOop)) { - BasicType basicType = java_lang_Class::primitive_type(javaClassOop); - return JNIHandles::make_local(THREAD, VMExits::createRiTypePrimitive((int) basicType, THREAD)); - } else { - KlassHandle klass = java_lang_Class::as_klassOop(javaClassOop); - Handle name = java_lang_String::create_from_symbol(klass->name(), CHECK_NULL); - - oop type = C1XCompiler::createHotSpotTypeResolved(klass, name, CHECK_NULL); - return JNIHandles::make_local(THREAD, type); - } -} - - -// helpers used to set fields in the HotSpotVMConfig object -jfieldID getFieldID(JNIEnv* env, jobject obj, const char* name, const char* sig) { - jfieldID id = env->GetFieldID(env->GetObjectClass(obj), name, sig); - if (id == NULL) { - TRACE_C1X_1("field not found: %s (%s)", name, sig); - fatal("field not found"); - } - return id; -} - -void set_boolean(JNIEnv* env, jobject obj, const char* name, bool value) { env->SetBooleanField(obj, getFieldID(env, obj, name, "Z"), value); } -void set_int(JNIEnv* env, jobject obj, const char* name, int value) { env->SetIntField(obj, getFieldID(env, obj, name, "I"), value); } -void set_long(JNIEnv* env, jobject obj, const char* name, jlong value) { env->SetLongField(obj, getFieldID(env, obj, name, "J"), value); } -void set_object(JNIEnv* env, jobject obj, const char* name, jobject value) { env->SetObjectField(obj, getFieldID(env, obj, name, "Ljava/lang/Object;"), value); } -void set_int_array(JNIEnv* env, jobject obj, const char* name, jarray value) { env->SetObjectField(obj, getFieldID(env, obj, name, "[I"), value); } - -jboolean get_boolean(JNIEnv* env, jobject obj, const char* name) { return env->GetBooleanField(obj, getFieldID(env, obj, name, "Z")); } -jint get_int(JNIEnv* env, jobject obj, const char* name) { return env->GetIntField(obj, getFieldID(env, obj, name, "I")); } -jlong get_long(JNIEnv* env, jobject obj, const char* name) { return env->GetLongField(obj, getFieldID(env, obj, name, "J")); } -jobject get_object(JNIEnv* env, jobject obj, const char* name) { return env->GetObjectField(obj, getFieldID(env, obj, name, "Ljava/lang/Object;")); } -jobject get_object(JNIEnv* env, jobject obj, const char* name, const char* sig) { return env->GetObjectField(obj, getFieldID(env, obj, name, sig)); } - - -BasicType basicTypes[] = { T_BOOLEAN, T_BYTE, T_SHORT, T_CHAR, T_INT, T_FLOAT, T_LONG, T_DOUBLE, T_OBJECT }; -int basicTypeCount = sizeof(basicTypes) / sizeof(BasicType); - -// public HotSpotVMConfig getConfiguration(); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_getConfiguration(JNIEnv *env, jobject) { - jclass klass = env->FindClass("com/oracle/max/graal/runtime/HotSpotVMConfig"); - assert(klass != NULL, "HotSpot vm config class not found"); - jobject config = env->AllocObject(klass); -#ifdef _WIN64 - set_boolean(env, config, "windowsOs", true); -#else - set_boolean(env, config, "windowsOs", false); -#endif - set_boolean(env, config, "verifyPointers", VerifyOops); - set_boolean(env, config, "useFastLocking", UseFastLocking); - set_boolean(env, config, "useFastNewObjectArray", UseFastNewObjectArray); - set_boolean(env, config, "useFastNewTypeArray", UseFastNewTypeArray); - set_int(env, config, "codeEntryAlignment", CodeEntryAlignment); - set_int(env, config, "vmPageSize", os::vm_page_size()); - set_int(env, config, "stackShadowPages", StackShadowPages); - set_int(env, config, "hubOffset", oopDesc::klass_offset_in_bytes()); - set_int(env, config, "arrayLengthOffset", arrayOopDesc::length_offset_in_bytes()); - set_int(env, config, "klassStateOffset", instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc)); - set_int(env, config, "klassStateFullyInitialized", (int)instanceKlass::fully_initialized); - set_int(env, config, "threadTlabTopOffset", in_bytes(JavaThread::tlab_top_offset())); - set_int(env, config, "threadTlabEndOffset", in_bytes(JavaThread::tlab_end_offset())); - set_int(env, config, "threadObjectOffset", in_bytes(JavaThread::threadObj_offset())); - set_int(env, config, "instanceHeaderPrototypeOffset", Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()); - set_int(env, config, "threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset())); - set_int(env, config, "threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset())); - set_int(env, config, "threadMultiNewArrayStorage", in_bytes(JavaThread::c1x_multinewarray_storage_offset())); - set_int(env, config, "classMirrorOffset", klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes()); - - set_long(env, config, "debugStub", VmIds::addStub((address)warning)); - set_long(env, config, "instanceofStub", VmIds::addStub(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); - set_long(env, config, "verifyPointerStub", VmIds::addStub(Runtime1::entry_for(Runtime1::c1x_verify_pointer_id))); - set_long(env, config, "newInstanceStub", VmIds::addStub(Runtime1::entry_for(Runtime1::fast_new_instance_init_check_id))); - set_long(env, config, "unresolvedNewInstanceStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_instance_id))); - set_long(env, config, "newTypeArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_type_array_id))); - set_long(env, config, "newObjectArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_object_array_id))); - set_long(env, config, "newMultiArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_multi_array_id))); - set_long(env, config, "loadKlassStub", VmIds::addStub(Runtime1::entry_for(Runtime1::load_klass_patching_id))); - set_long(env, config, "accessFieldStub", VmIds::addStub(Runtime1::entry_for(Runtime1::access_field_patching_id))); - set_long(env, config, "resolveStaticCallStub", VmIds::addStub(SharedRuntime::get_resolve_static_call_stub())); - set_long(env, config, "inlineCacheMissStub", VmIds::addStub(SharedRuntime::get_ic_miss_stub())); - set_long(env, config, "unwindExceptionStub", VmIds::addStub(Runtime1::entry_for(Runtime1::c1x_unwind_exception_call_id))); - set_long(env, config, "handleExceptionStub", VmIds::addStub(Runtime1::entry_for(Runtime1::handle_exception_nofpu_id))); - set_long(env, config, "handleDeoptStub", VmIds::addStub(SharedRuntime::deopt_blob()->unpack())); - set_long(env, config, "monitorEnterStub", VmIds::addStub(Runtime1::entry_for(Runtime1::monitorenter_id))); - set_long(env, config, "monitorExitStub", VmIds::addStub(Runtime1::entry_for(Runtime1::monitorexit_id))); - set_long(env, config, "fastMonitorEnterStub", VmIds::addStub(Runtime1::entry_for(Runtime1::c1x_monitorenter_id))); - set_long(env, config, "fastMonitorExitStub", VmIds::addStub(Runtime1::entry_for(Runtime1::c1x_monitorexit_id))); - set_long(env, config, "safepointPollingAddress", (jlong)(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()))); - - BarrierSet* bs = Universe::heap()->barrier_set(); - switch (bs->kind()) { - case BarrierSet::CardTableModRef: - case BarrierSet::CardTableExtension: { - jlong base = (jlong)((CardTableModRefBS*)bs)->byte_map_base; - assert(base != 0, "unexpected byte_map_base"); - set_long(env, config, "cardtableStartAddress", base); - set_int(env, config, "cardtableShift", CardTableModRefBS::card_shift); - break; - } - case BarrierSet::ModRef: - case BarrierSet::Other: - set_long(env, config, "cardtableStartAddress", 0); - set_int(env, config, "cardtableShift", 0); - // No post barriers - break; -#ifndef SERIALGC - case BarrierSet::G1SATBCT: - case BarrierSet::G1SATBCTLogging: -#endif // SERIALGC - default: - ShouldNotReachHere(); - } - - jintArray arrayOffsets = env->NewIntArray(basicTypeCount); - for (int i=0; iSetIntArrayRegion(arrayOffsets, i, 1, &offset); - } - set_int_array(env, config, "arrayOffsets", arrayOffsets); - set_int(env, config, "arrayClassElementOffset", objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc)); - return config; -} - -// public void installMethod(HotSpotTargetMethod targetMethod); -JNIEXPORT void JNICALL Java_com_oracle_graal_runtime_VMEntries_installMethod(JNIEnv *jniEnv, jobject, jobject targetMethod) { - VM_ENTRY_MARK; - CodeInstaller installer(JNIHandles::resolve(targetMethod)); -} - -// public HotSpotProxy installStub(HotSpotTargetMethod targetMethod, String name); -JNIEXPORT jlong JNICALL Java_com_oracle_graal_runtime_VMEntries_installStub(JNIEnv *jniEnv, jobject, jobject targetMethod) { - VM_ENTRY_MARK; - jlong id; - CodeInstaller installer(JNIHandles::resolve(targetMethod), id); - return id; -} - -// public void recordBailout(String reason); -JNIEXPORT void JNICALL Java_com_oracle_graal_runtime_VMEntries_recordBailout(JNIEnv *jniEnv, jobject, jobject message) { - if (C1XBailoutIsFatal) { - Handle msg = JNIHandles::resolve(message); - if (!msg.is_null()) { - java_lang_String::print(msg, tty); - } - vm_abort(false); - } -} - - - - -#define CC (char*) /*cast a literal from (const char*)*/ -#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) - -#define PROXY "J" -#define TYPE "Lcom/sun/cri/ri/RiType;" -#define RESOLVED_TYPE "Lcom/oracle/max/graal/runtime/HotSpotTypeResolved;" -#define METHOD "Lcom/sun/cri/ri/RiMethod;" -#define SIGNATURE "Lcom/sun/cri/ri/RiSignature;" -#define FIELD "Lcom/sun/cri/ri/RiField;" -#define CONSTANT_POOL "Lcom/sun/cri/ri/RiConstantPool;" -#define EXCEPTION_HANDLERS "[Lcom/sun/cri/ri/RiExceptionHandler;" -#define TARGET_METHOD "Lcom/oracle/max/graal/runtime/HotSpotTargetMethod;" -#define CONFIG "Lcom/oracle/max/graal/runtime/HotSpotVMConfig;" -#define HS_METHOD "Lcom/oracle/max/graal/runtime/HotSpotMethod;" -#define CI_CONSTANT "Lcom/sun/cri/ci/CiConstant;" -#define CI_KIND "Lcom/sun/cri/ci/CiKind;" -#define STRING "Ljava/lang/String;" -#define OBJECT "Ljava/lang/Object;" -#define CLASS "Ljava/lang/Class;" - -JNINativeMethod VMEntries_methods[] = { - {CC"RiMethod_code", CC"("PROXY")[B", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1code)}, - {CC"RiMethod_maxStackSize", CC"("PROXY")I", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1maxStackSize)}, - {CC"RiMethod_maxLocals", CC"("PROXY")I", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1maxLocals)}, - {CC"RiMethod_holder", CC"("PROXY")"TYPE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1holder)}, - {CC"RiMethod_signature", CC"("PROXY")"STRING, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1signature)}, - {CC"RiMethod_accessFlags", CC"("PROXY")I", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1accessFlags)}, - {CC"RiMethod_exceptionHandlers", CC"("PROXY")"EXCEPTION_HANDLERS, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1exceptionHandlers)}, - {CC"RiMethod_hasBalancedMonitors", CC"("PROXY")Z", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1hasBalancedMonitors)}, - {CC"RiMethod_uniqueConcreteMethod", CC"("PROXY")"METHOD, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1uniqueConcreteMethod)}, - {CC"RiSignature_lookupType", CC"("STRING RESOLVED_TYPE")"TYPE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiSignature_1lookupType)}, - {CC"RiConstantPool_lookupConstant", CC"("PROXY"I)"OBJECT, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupConstant)}, - {CC"RiConstantPool_lookupMethod", CC"("PROXY"IB)"METHOD, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupMethod)}, - {CC"RiConstantPool_lookupSignature", CC"("PROXY"I)"SIGNATURE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupSignature)}, - {CC"RiConstantPool_lookupType", CC"("PROXY"I)"TYPE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupType)}, - {CC"RiConstantPool_lookupField", CC"("PROXY"IB)"FIELD, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupField)}, - {CC"RiType_constantPool", CC"("RESOLVED_TYPE")"CONSTANT_POOL, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_1constantPool)}, - {CC"RiType_resolveMethodImpl", CC"("RESOLVED_TYPE STRING STRING")"METHOD, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_3resolveMethodImpl)}, - {CC"RiType_isSubtypeOf", CC"("RESOLVED_TYPE TYPE")Z", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_2isSubtypeOf)}, - {CC"RiType_componentType", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_1componentType)}, - {CC"RiType_uniqueConcreteSubtype", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_1uniqueConcreteSubtype)}, - {CC"RiType_superType", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_1superType)}, - {CC"RiType_arrayOf", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_1arrayOf)}, - {CC"getPrimitiveArrayType", CC"("CI_KIND")"TYPE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_getPrimitiveArrayType)}, - {CC"getType", CC"("CLASS")"TYPE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_getType)}, - {CC"getConfiguration", CC"()"CONFIG, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_getConfiguration)}, - {CC"installMethod", CC"("TARGET_METHOD")V", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_installMethod)}, - {CC"installStub", CC"("TARGET_METHOD")"PROXY, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_installStub)}, - {CC"recordBailout", CC"("STRING")V", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_recordBailout)} -}; - -int VMEntries_methods_count() { - return sizeof(VMEntries_methods) / sizeof(JNINativeMethod); -} diff -r 2fb867285938 -r c23d45daff9b src/share/vm/c1x/graalVMEntries.hpp --- a/src/share/vm/c1x/graalVMEntries.hpp Wed Jun 08 13:40:08 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ - -#include "prims/jni.h" - -extern JNINativeMethod VMEntries_methods[]; -int VMEntries_methods_count(); - -// nothing here - no need to define the jni method implementations in a header file - - diff -r 2fb867285938 -r c23d45daff9b src/share/vm/c1x/graalVMExits.cpp --- a/src/share/vm/c1x/graalVMExits.cpp Wed Jun 08 13:40:08 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,258 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ - -#include "precompiled.hpp" -#include "c1x/c1x_VMExits.hpp" - -// this is a *global* handle -jobject VMExits::_compilerPermObject; -jobject VMExits::_vmExitsPermObject; -jobject VMExits::_vmExitsPermKlass; - -KlassHandle VMExits::vmExitsKlass() { - if (JNIHandles::resolve(_vmExitsPermKlass) == NULL) { - klassOop result = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_c1x_VMExits(), SystemDictionary::java_system_loader(), NULL, Thread::current()); - check_not_null(result, "Couldn't find class com.sun.hotspot.c1x.VMExits"); - _vmExitsPermKlass = JNIHandles::make_global(result); - } - return KlassHandle((klassOop)JNIHandles::resolve_non_null(_vmExitsPermKlass)); -} - -Handle VMExits::compilerInstance() { - if (JNIHandles::resolve(_compilerPermObject) == NULL) { - KlassHandle compilerImplKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_c1x_CompilerImpl(), SystemDictionary::java_system_loader(), NULL, Thread::current()); - check_not_null(compilerImplKlass(), "Couldn't find class com.sun.hotspot.c1x.CompilerImpl"); - - JavaValue result(T_OBJECT); - JavaCalls::call_static(&result, compilerImplKlass, vmSymbols::getInstance_name(), vmSymbols::getInstance_signature(), Thread::current()); - check_pending_exception("Couldn't get Compiler"); - _compilerPermObject = JNIHandles::make_global((oop) result.get_jobject()); - } - return Handle(JNIHandles::resolve_non_null(_compilerPermObject)); -} - -Handle VMExits::instance() { - if (JNIHandles::resolve(_vmExitsPermObject) == NULL) { - KlassHandle compilerKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_c1x_Compiler(), SystemDictionary::java_system_loader(), NULL, Thread::current()); - check_not_null(compilerKlass(), "Couldn't find class com.sun.hotspot.c1x.Compiler"); - - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.set_receiver(compilerInstance()); - JavaCalls::call_interface(&result, compilerKlass, vmSymbols::getVMExits_name(), vmSymbols::getVMExits_signature(), &args, Thread::current()); - check_pending_exception("Couldn't get VMExits"); - _vmExitsPermObject = JNIHandles::make_global((oop) result.get_jobject()); - } - return Handle(JNIHandles::resolve_non_null(_vmExitsPermObject)); -} - -void VMExits::initializeCompiler() { - KlassHandle compilerImplKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_c1x_CompilerImpl(), SystemDictionary::java_system_loader(), NULL, Thread::current()); - check_not_null(compilerImplKlass(), "Couldn't find class com.sun.hotspot.c1x.CompilerImpl"); - - JavaValue result(T_VOID); - JavaCalls::call_static(&result, compilerImplKlass, vmSymbols::initialize_name(), vmSymbols::void_method_signature(), Thread::current()); - check_pending_exception("Couldn't initialize compiler"); -} - -jboolean VMExits::setOption(Handle option) { - assert(!option.is_null(), ""); - KlassHandle compilerKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_c1x_HotSpotOptions(), SystemDictionary::java_system_loader(), NULL, Thread::current()); - check_not_null(compilerKlass(), "Couldn't find class com.sun.hotspot.c1x.HotSpotOptions"); - - Thread* THREAD = Thread::current(); - JavaValue result(T_BOOLEAN); - JavaCalls::call_static(&result, compilerKlass, vmSymbols::setOption_name(), vmSymbols::setOption_signature(), option, THREAD); - check_pending_exception("Error while calling setOption"); - return result.get_jboolean(); -} - -void VMExits::setDefaultOptions() { - KlassHandle compilerKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_c1x_HotSpotOptions(), SystemDictionary::java_system_loader(), NULL, Thread::current()); - check_not_null(compilerKlass(), "Couldn't find class com.sun.hotspot.c1x.HotSpotOptions"); - - Thread* THREAD = Thread::current(); - JavaValue result(T_VOID); - JavaCalls::call_static(&result, compilerKlass, vmSymbols::setDefaultOptions_name(), vmSymbols::void_method_signature(), THREAD); - check_pending_exception("Error while calling setDefaultOptions"); -} - -void VMExits::compileMethod(jlong methodVmId, Handle name, int entry_bci) { - assert(!name.is_null(), "just checking"); - Thread* THREAD = Thread::current(); - JavaValue result(T_VOID); - JavaCallArguments args; - args.push_oop(instance()); - args.push_long(methodVmId); - args.push_oop(name); - args.push_int(entry_bci); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::compileMethod_name(), vmSymbols::compileMethod_signature(), &args, THREAD); - check_pending_exception("Error while calling compileMethod"); -} - -oop VMExits::createRiMethodResolved(jlong vmId, Handle name, TRAPS) { - assert(!name.is_null(), "just checking"); - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(instance()); - args.push_long(vmId); - args.push_oop(name); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiMethodResolved_name(), vmSymbols::createRiMethodResolved_signature(), &args, THREAD); - check_pending_exception("Error while calling createRiMethodResolved"); - return (oop) result.get_jobject(); -} - -oop VMExits::createRiMethodUnresolved(Handle name, Handle signature, Handle holder, TRAPS) { - assert(!name.is_null(), "just checking"); - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(instance()); - args.push_oop(name); - args.push_oop(signature); - args.push_oop(holder); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiMethodUnresolved_name(), vmSymbols::createRiMethodUnresolved_signature(), &args, THREAD); - check_pending_exception("Error while calling createRiMethodUnresolved"); - return (oop) result.get_jobject(); -} - -oop VMExits::createRiField(Handle holder, Handle name, Handle type, int index, int flags, TRAPS) { - assert(!holder.is_null(), "just checking"); - assert(!name.is_null(), "just checking"); - assert(!type.is_null(), "just checking"); - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(instance()); - args.push_oop(holder); - args.push_oop(name); - args.push_oop(type); - args.push_int(index); - args.push_int(flags); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiField_name(), vmSymbols::createRiField_signature(), &args, THREAD); - check_pending_exception("Error while calling createRiField"); - assert(result.get_type() == T_OBJECT, "just checking"); - return (oop) result.get_jobject(); -} - -oop VMExits::createRiType(jlong vmId, Handle name, TRAPS) { - assert(!name.is_null(), "just checking"); - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(instance()); - args.push_long(vmId); - args.push_oop(name); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiType_name(), vmSymbols::createRiType_signature(), &args, THREAD); - check_pending_exception("Error while calling createRiType"); - return (oop) result.get_jobject(); -} - -oop VMExits::createRiTypePrimitive(int basic_type, TRAPS) { - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(instance()); - args.push_int(basic_type); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiTypePrimitive_name(), vmSymbols::createRiTypePrimitive_signature(), &args, THREAD); - check_pending_exception("Error while calling createRiTypePrimitive"); - return (oop) result.get_jobject(); -} - -oop VMExits::createRiTypeUnresolved(Handle name, TRAPS) { - assert(!name.is_null(), "just checking"); - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(instance()); - args.push_oop(name); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiTypeUnresolved_name(), vmSymbols::createRiTypeUnresolved_signature(), &args, THREAD); - check_pending_exception("Error while calling createRiTypeUnresolved"); - return (oop) result.get_jobject(); -} - -oop VMExits::createRiConstantPool(jlong vmId, TRAPS) { - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(instance()); - args.push_long(vmId); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiConstantPool_name(), vmSymbols::createRiConstantPool_signature(), &args, THREAD); - check_pending_exception("Error while calling createRiConstantPool"); - return (oop) result.get_jobject(); -} - -oop VMExits::createRiSignature(Handle name, TRAPS) { - assert(!name.is_null(), "just checking"); - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(instance()); - args.push_oop(name); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiSignature_name(), vmSymbols::createRiSignature_signature(), &args, THREAD); - check_pending_exception("Error while calling createRiSignature"); - return (oop) result.get_jobject(); -} - -oop VMExits::createCiConstant(Handle kind, jlong value, TRAPS) { - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(instance()); - args.push_oop(kind()); - args.push_long(value); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createCiConstant_name(), vmSymbols::createCiConstant_signature(), &args, THREAD); - check_pending_exception("Error while calling createCiConstantFloat"); - return (oop) result.get_jobject(); - -} - -oop VMExits::createCiConstantFloat(jfloat value, TRAPS) { - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(instance()); - args.push_float(value); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createCiConstantFloat_name(), vmSymbols::createCiConstantFloat_signature(), &args, THREAD); - check_pending_exception("Error while calling createCiConstantFloat"); - return (oop) result.get_jobject(); - -} - -oop VMExits::createCiConstantDouble(jdouble value, TRAPS) { - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(instance()); - args.push_double(value); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createCiConstantDouble_name(), vmSymbols::createCiConstantDouble_signature(), &args, THREAD); - check_pending_exception("Error while calling createCiConstantDouble"); - return (oop) result.get_jobject(); -} - -oop VMExits::createCiConstantObject(Handle object, TRAPS) { - JavaValue result(T_OBJECT); - JavaCallArguments args; - /* - args.push_oop(instance()); - args.push_oop(object); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createCiConstantObject_name(), vmSymbols::createCiConstantObject_signature(), &args, THREAD); - check_pending_exception("Error while calling createCiConstantObject"); - */ - - - KlassHandle klass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_cri_ci_CiConstant(), SystemDictionary::java_system_loader(), NULL, Thread::current()); - JavaCalls::call_static(&result, klass(), vmSymbols::forObject_name(), vmSymbols::createCiConstantObject_signature(), object, THREAD); - check_pending_exception("Error while calling CiConstant.forObject"); - return (oop) result.get_jobject(); -} diff -r 2fb867285938 -r c23d45daff9b src/share/vm/c1x/graalVMExits.hpp --- a/src/share/vm/c1x/graalVMExits.hpp Wed Jun 08 13:40:08 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ - -#include "memory/allocation.hpp" -#include "oops/oop.hpp" -#include "runtime/handles.hpp" -#include "runtime/thread.hpp" -#include "classfile/javaClasses.hpp" -#include "runtime/jniHandles.hpp" -#include "runtime/javaCalls.hpp" - -class VMExits : public AllStatic { - -private: - static jobject _compilerPermObject; - static jobject _vmExitsPermObject; - static jobject _vmExitsPermKlass; - - static KlassHandle vmExitsKlass(); - static Handle instance(); - -public: - static void initializeCompiler(); - - static Handle compilerInstance(); - - // public static boolean HotSpotOptions.setOption(String option); - static jboolean setOption(Handle option); - - // public static void HotSpotOptions.setDefaultOptions(); - static void setDefaultOptions(); - - // public abstract void compileMethod(long vmId, String name, int entry_bci); - static void compileMethod(jlong vmId, Handle name, int entry_bci); - - // public abstract RiMethod createRiMethodResolved(long vmId, String name); - static oop createRiMethodResolved(jlong vmId, Handle name, TRAPS); - - // public abstract RiMethod createRiMethodUnresolved(String name, String signature, RiType holder); - static oop createRiMethodUnresolved(Handle name, Handle signature, Handle holder, TRAPS); - - // public abstract RiField createRiField(RiType holder, String name, RiType type, int flags, int offset); - static oop createRiField(Handle holder, Handle name, Handle type, int index, int flags, TRAPS); - - // public abstract RiType createRiType(long vmId, String name); - static oop createRiType(jlong vmId, Handle name, TRAPS); - - // public abstract RiType createRiTypeUnresolved(String name); - static oop createRiTypeUnresolved(Handle name, TRAPS); - - // public abstract RiConstantPool createRiConstantPool(long vmId); - static oop createRiConstantPool(jlong vmId, TRAPS); - - // public abstract RiType createRiTypePrimitive(int basicType); - static oop createRiTypePrimitive(int basicType, TRAPS); - - // public abstract RiSignature createRiSignature(String signature); - static oop createRiSignature(Handle name, TRAPS); - - // public abstract CiConstant createCiConstant(CiKind kind, long value); - static oop createCiConstant(Handle kind, jlong value, TRAPS); - - // public abstract CiConstant createCiConstantFloat(float value); - static oop createCiConstantFloat(jfloat value, TRAPS); - - // public abstract CiConstant createCiConstantDouble(double value); - static oop createCiConstantDouble(jdouble value, TRAPS); - - // public abstract CiConstant createCiConstantObject(long vmId); - static oop createCiConstantObject(Handle object, TRAPS); -}; - -inline void check_pending_exception(const char* message, bool dump_core = false) { - Thread* THREAD = Thread::current(); - if (THREAD->has_pending_exception()) { - Handle exception = PENDING_EXCEPTION; - CLEAR_PENDING_EXCEPTION; - tty->print_cr("%s", message); - java_lang_Throwable::print(exception, tty); - tty->cr(); - java_lang_Throwable::print_stack_trace(exception(), tty); - vm_abort(dump_core); - } -} - -inline void check_not_null(void* value, const char* message, bool dump_core = false) { - if (value == NULL) { - tty->print_cr("%s", message); - vm_abort(dump_core); - } -} diff -r 2fb867285938 -r c23d45daff9b src/share/vm/c1x/graalVmIds.cpp --- a/src/share/vm/c1x/graalVmIds.cpp Wed Jun 08 13:40:08 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ - -#include "precompiled.hpp" -#include "c1x/c1x_VmIds.hpp" -#include "ci/ciUtilities.hpp" - -// VmIds implementation - -GrowableArray
* VmIds::_stubs = NULL; -GrowableArray* VmIds::_localHandles = NULL; - - -void VmIds::initializeObjects() { - if (_stubs == NULL) { - assert(_localHandles == NULL, "inconsistent state"); - _stubs = new (ResourceObj::C_HEAP) GrowableArray
(64, true); - _localHandles = new (ResourceObj::C_HEAP) GrowableArray (64, true); - } - assert(_localHandles->length() == 0, "invalid state"); -} - -void VmIds::cleanupLocalObjects() { - for (int i = 0; i < _localHandles->length(); i++) { - JNIHandles::destroy_global(_localHandles->at(i)); - } - _localHandles->clear(); -} - -jlong VmIds::addStub(address stub) { - assert(!_stubs->contains(stub), "duplicate stub"); - return _stubs->append(stub) | STUB; -} - -jlong VmIds::add(Handle obj, jlong type) { - assert(!obj.is_null(), "cannot add NULL handle"); - int idx = -1; - for (int i = 0; i < _localHandles->length(); i++) - if (JNIHandles::resolve_non_null(_localHandles->at(i)) == obj()) { - idx = i; - break; - } - if (idx == -1) { - if (JavaThread::current()->thread_state() == _thread_in_vm) { - idx = _localHandles->append(JNIHandles::make_global(obj)); - } else { - VM_ENTRY_MARK; - idx = _localHandles->append(JNIHandles::make_global(obj)); - } - } - return idx | type; -} - -address VmIds::getStub(jlong id) { - assert((id & TYPE_MASK) == STUB, "wrong id type, STUB expected"); - assert((id & ~TYPE_MASK) >= 0 && (id & ~TYPE_MASK) < _stubs->length(), "STUB index out of bounds"); - return _stubs->at(id & ~TYPE_MASK); -} - -oop VmIds::getObject(jlong id) { - assert((id & TYPE_MASK) != STUB, "wrong id type"); - assert((id & ~TYPE_MASK) >= 0 && (id & ~TYPE_MASK) < _localHandles->length(), "index out of bounds"); - return JNIHandles::resolve_non_null(_localHandles->at(id & ~TYPE_MASK)); -} - diff -r 2fb867285938 -r c23d45daff9b src/share/vm/c1x/graalVmIds.hpp --- a/src/share/vm/c1x/graalVmIds.hpp Wed Jun 08 13:40:08 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ - -#include "memory/allocation.hpp" -#include "utilities/growableArray.hpp" -#include "oops/oop.hpp" -#include "runtime/handles.hpp" -#include "runtime/thread.hpp" -#include "classfile/javaClasses.hpp" -#include "runtime/jniHandles.hpp" - -class VmIds : public AllStatic { - -private: - static GrowableArray
* _stubs; - static GrowableArray* _localHandles; - - static oop getObject(jlong id); - -public: - // these constants needs to have the same values as the one in HotSpotProxy.java - static const jlong STUB = 0x100000000000000LL; // address - static const jlong METHOD = 0x200000000000000LL; // methodOop - static const jlong CLASS = 0x300000000000000LL; // klassOop - static const jlong CONSTANT_POOL = 0x500000000000000LL; // constantPoolOop - static const jlong CONSTANT = 0x600000000000000LL; // oop - static const jlong TYPE_MASK = 0xf00000000000000LL; - static const jlong DUMMY_CONSTANT = 0x6ffffffffffffffLL; - - // Initializes the VmIds for a compilation, by creating the arrays - static void initializeObjects(); - // Cleans up after a compilation, by deallocating the arrays - static void cleanupLocalObjects(); - - // Adds a stub address, and returns the corresponding vmId (which is of type STUB) - static jlong addStub(address stub); - - // Adds an object, and returns the corresponding vmId (with the given type) - static jlong add(Handle obj, jlong type); - - // Adds an object, and returns the corresponding vmId (the type of which is determined by the template parameter) - template static jlong add(T obj); - - - // Returns the stub address with the given vmId - static address getStub(jlong id); - // Returns the stub address with the given vmId taken from a java.lang.Long - static address getStub(oop id); - - // Returns the object with the given id, the return type is defined by the template parameter (which must correspond to the actual type of the vmId) - template static T get(jlong id); - - - // Helper function to convert a symbol to a java.lang.String object - template static T toString(Symbol* symbol, TRAPS); - - // Helper function to convert a java.lang.String object to a symbol (this will return NULL if the symbol doesn't exist in the system) - static Symbol* toSymbol(jstring string); - - // Helper function to get the contents of a java.lang.Long - static jlong getBoxedLong(oop obj); -}; - - -template <> inline jlong VmIds::add(methodOop obj){ - assert(obj != NULL, "trying to add NULL"); - assert(obj->is_method(), "trying to add mistyped object"); - return add(Handle(obj), METHOD); -} -template <> inline jlong VmIds::add(klassOop obj) { - assert(obj != NULL, "trying to add NULL"); - assert(obj->is_klass(), "trying to add mistyped object"); - return add(Handle(obj), CLASS); -} -template <> inline jlong VmIds::add(constantPoolOop obj) { - assert(obj != NULL, "trying to add NULL"); - assert(obj->is_constantPool(), "trying to add mistyped object"); - return add(Handle(obj), CONSTANT_POOL); -} -template <> inline jlong VmIds::add(oop obj) { - assert(obj != NULL, "trying to add NULL"); - assert(obj->is_oop(), "trying to add mistyped object"); - return add(Handle(obj), CONSTANT); -} - - -template <> inline methodOop VmIds::get(jlong id){ - assert((id & TYPE_MASK) == METHOD, "METHOD expected"); - assert(getObject(id)->is_method(), "methodOop expected"); - return (methodOop)getObject(id); -} -template <> inline klassOop VmIds::get(jlong id) { - assert((id & TYPE_MASK) == CLASS, "CLASS expected"); - assert(getObject(id)->is_klass(), "klassOop expected"); - return (klassOop)getObject(id); -} -template <> inline constantPoolOop VmIds::get(jlong id) { - assert((id & TYPE_MASK) == CONSTANT_POOL, "CONSTANT_POOL expected"); - assert(getObject(id)->is_constantPool(), "constantPoolOop expected"); - return (constantPoolOop)getObject(id); -} -template <> inline oop VmIds::get(jlong id) { - assert((id & TYPE_MASK) == CONSTANT, "CONSTANT expected"); - assert(getObject(id)->is_oop(true), "oop expected"); - return (oop)getObject(id); -} - -inline address VmIds::getStub(oop obj) { - return getStub(getBoxedLong(obj)); -} - -template <> inline Handle VmIds::toString(Symbol* symbol, TRAPS) { - return java_lang_String::create_from_symbol(symbol, THREAD); -} -template <> inline oop VmIds::toString(Symbol* symbol, TRAPS) { - return toString(symbol, THREAD)(); -} -template <> inline jstring VmIds::toString(Symbol* symbol, TRAPS) { - return (jstring)JNIHandles::make_local(toString(symbol, THREAD)); -} -template <> inline jobject VmIds::toString(Symbol* symbol, TRAPS) { - return JNIHandles::make_local(toString(symbol, THREAD)); -} - -inline Symbol* VmIds::toSymbol(jstring string) { - return java_lang_String::as_symbol_or_null(JNIHandles::resolve(string)); -} - -inline jlong VmIds::getBoxedLong(oop obj) { - assert(obj->is_oop(true), "cannot unbox null or non-oop"); - return obj->long_field(java_lang_boxing_object::value_offset_in_bytes(T_LONG)); -} diff -r 2fb867285938 -r c23d45daff9b src/share/vm/graal/graalCodeInstaller.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Wed Jun 08 13:40:25 2011 +0200 @@ -0,0 +1,740 @@ +/* + * Copyright (c) 2011, 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. + */ + +#include "precompiled.hpp" +#include "c1x/c1x_Compiler.hpp" +#include "c1x/c1x_CodeInstaller.hpp" +#include "c1x/c1x_JavaAccess.hpp" +#include "c1x/c1x_VmIds.hpp" +#include "c1/c1_Runtime1.hpp" +#include "classfile/vmSymbols.hpp" +#include "vmreg_x86.inline.hpp" + + +// TODO this should be handled in a more robust way - not hard coded... +Register CPU_REGS[] = { rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15 }; +bool OOP_ALLOWED[] = {true, true, true, true, false, false, true, true, true, true, false, true, true, true, true, true}; +const static int NUM_CPU_REGS = sizeof(CPU_REGS) / sizeof(Register); +XMMRegister XMM_REGS[] = { xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 }; +const static int NUM_XMM_REGS = sizeof(XMM_REGS) / sizeof(XMMRegister); +const static int NUM_REGS = NUM_CPU_REGS + NUM_XMM_REGS; +const static jlong NO_REF_MAP = 0x8000000000000000L; + +// convert c1x register indices (as used in oop maps) to hotspot registers +VMReg get_hotspot_reg(jint c1x_reg) { + + assert(c1x_reg >= 0 && c1x_reg < NUM_REGS, "invalid register number"); + if (c1x_reg < NUM_CPU_REGS) { + return CPU_REGS[c1x_reg]->as_VMReg(); + } else { + return XMM_REGS[c1x_reg - NUM_CPU_REGS]->as_VMReg(); + } +} + +static bool is_bit_set(oop bit_map, int i) { + const int MapWordBits = 64; + if (i < MapWordBits) { + jlong low = CiBitMap::low(bit_map); + return (low & (1LL << i)) != 0; + } else { + jint extra_idx = (i - MapWordBits) / MapWordBits; + arrayOop extra = (arrayOop) CiBitMap::extra(bit_map); + assert(extra_idx >= 0 && extra_idx < extra->length(), "unexpected index"); + jlong word = ((jlong*) extra->base(T_LONG))[extra_idx]; + return (word & (1LL << (i % MapWordBits))) != 0; + } +} + +// creates a hotspot oop map out of the byte arrays provided by CiDebugInfo +static OopMap* create_oop_map(jint frame_size, jint parameter_count, oop debug_info) { + OopMap* map = new OopMap(frame_size, parameter_count); + oop register_map = (oop) CiDebugInfo::registerRefMap(debug_info); + oop frame_map = (oop) CiDebugInfo::frameRefMap(debug_info); + + if (register_map != NULL) { + assert(CiBitMap::size(register_map) == (unsigned) NUM_CPU_REGS, "unexpected register_map length"); + for (jint i = 0; i < NUM_CPU_REGS; i++) { + bool is_oop = is_bit_set(register_map, i); + VMReg reg = get_hotspot_reg(i); + if (is_oop) { + assert(OOP_ALLOWED[i], "this register may never be an oop, register map misaligned?"); + map->set_oop(reg); + } else { + map->set_value(reg); + } + } + } + + if (frame_size > 0) { + assert(CiBitMap::size(frame_map) == frame_size / HeapWordSize, "unexpected frame_map length"); + + for (jint i = 0; i < frame_size / HeapWordSize; i++) { + bool is_oop = is_bit_set(frame_map, i); + // hotspot stack slots are 4 bytes + VMReg reg = VMRegImpl::stack2reg(i * 2); + if (is_oop) { + map->set_oop(reg); + } else { + map->set_value(reg); + } + } + } else { + assert(frame_map == NULL || CiBitMap::size(frame_map) == 0, "cannot have frame_map for frames with size 0"); + } + + return map; +} + +// TODO: finish this - c1x doesn't provide any scope values at the moment +static ScopeValue* get_hotspot_value(oop value, int frame_size) { + if (value == CiValue::IllegalValue()) { + return new LocationValue(Location::new_stk_loc(Location::invalid, 0)); + } + + BasicType type = C1XCompiler::kindToBasicType(CiKind::typeChar(CiValue::kind(value))); + Location::Type locationType = Location::normal; + if (type == T_OBJECT || type == T_ARRAY) locationType = Location::oop; + if (value->is_a(CiRegisterValue::klass())) { + jint number = CiRegister::number(CiRegisterValue::reg(value)); + if (number < 16) { + return new LocationValue(Location::new_reg_loc(locationType, as_Register(number)->as_VMReg())); + } else { + return new LocationValue(Location::new_reg_loc(locationType, as_XMMRegister(number - 16)->as_VMReg())); + } + } else if (value->is_a(CiStackSlot::klass())) { + jint index = CiStackSlot::index(value); + if (index >= 0) { + return new LocationValue(Location::new_stk_loc(locationType, index * HeapWordSize)); + } else { + int frame_size_bytes = frame_size + 2 * HeapWordSize; + return new LocationValue(Location::new_stk_loc(locationType, -(index * HeapWordSize) + frame_size_bytes)); + } + } else if (value->is_a(CiConstant::klass())){ + oop obj = CiConstant::object(value); + jlong prim = CiConstant::primitive(value); + if (type == T_INT || type == T_FLOAT || type == T_SHORT || type == T_CHAR || type == T_BOOLEAN || type == T_BYTE) { + return new ConstantIntValue(*(jint*)&prim); + } else if (type == T_LONG || type == T_DOUBLE) { + return new ConstantLongValue(prim); + } else if (type == T_OBJECT) { + oop obj = CiConstant::object(value); + if (obj == NULL) { + return new ConstantOopWriteValue(NULL); + } else { + return new ConstantOopWriteValue(JNIHandles::make_global(obj)); + } + } else if (type == T_ADDRESS) { + return new ConstantLongValue(prim); + } + tty->print("%i", type); + } else { + value->klass()->print(); + value->print(); + } + ShouldNotReachHere(); + return NULL; +} + +// constructor used to create a method +CodeInstaller::CodeInstaller(Handle target_method) { + ciMethod *ciMethodObject = NULL; + { + No_Safepoint_Verifier no_safepoint; + _env = CURRENT_ENV; + + initialize_fields(target_method); + assert(_hotspot_method != NULL && _name == NULL, "installMethod needs NON-NULL method and NULL name"); + assert(_hotspot_method->is_a(HotSpotMethodResolved::klass()), "installMethod needs a HotSpotMethodResolved"); + + methodOop method = VmIds::get(HotSpotMethodResolved::vmId(_hotspot_method)); + ciMethodObject = (ciMethod *) _env->get_object(method); + _parameter_count = method->size_of_parameters(); + } + + // (very) conservative estimate: each site needs a relocation + //CodeBuffer buffer("temp c1x method", _total_size, _sites->length() * relocInfo::length_limit); + CodeBuffer buffer(CompilerThread::current()->get_buffer_blob()); + initialize_buffer(buffer); + process_exception_handlers(); + + int stack_slots = (_frame_size / HeapWordSize) + 2; // conversion to words, need to add two slots for ret address and frame pointer + ThreadToNativeFromVM t((JavaThread*) Thread::current()); + _env->register_method(ciMethodObject, -1, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table, + &_implicit_exception_table, C1XCompiler::instance(), _env->comp_level(), false, false); + +} + +// constructor used to create a stub +CodeInstaller::CodeInstaller(Handle target_method, jlong& id) { + No_Safepoint_Verifier no_safepoint; + _env = CURRENT_ENV; + + initialize_fields(target_method); + assert(_hotspot_method == NULL && _name != NULL, "installMethod needs NON-NULL name and NULL method"); + + // (very) conservative estimate: each site needs a relocation + CodeBuffer buffer(CompilerThread::current()->get_buffer_blob()); + initialize_buffer(buffer); + + const char* cname = java_lang_String::as_utf8_string(_name); + BufferBlob* blob = BufferBlob::create(strdup(cname), &buffer); // this is leaking strings... but only a limited number of stubs will be created + IF_TRACE_C1X_3 Disassembler::decode((CodeBlob*) blob); + id = VmIds::addStub(blob->code_begin()); +} + +void CodeInstaller::initialize_fields(Handle target_method) { + _citarget_method = HotSpotTargetMethod::targetMethod(target_method); + _hotspot_method = HotSpotTargetMethod::method(target_method); + _name = HotSpotTargetMethod::name(target_method); + _sites = (arrayOop) HotSpotTargetMethod::sites(target_method); + oop assumptions = CiTargetMethod::assumptions(_citarget_method); + if (assumptions != NULL) { + _assumptions = (arrayOop) CiAssumptions::list(assumptions); + } else { + _assumptions = NULL; + } + _exception_handlers = (arrayOop) HotSpotTargetMethod::exceptionHandlers(target_method); + + _code = (arrayOop) CiTargetMethod::targetCode(_citarget_method); + _code_size = CiTargetMethod::targetCodeSize(_citarget_method); + _frame_size = CiTargetMethod::frameSize(_citarget_method); + _custom_stack_area_offset = CiTargetMethod::customStackAreaOffset(_citarget_method); + + + // (very) conservative estimate: each site needs a constant section entry + _constants_size = _sites->length() * (BytesPerLong*2); + _total_size = align_size_up(_code_size, HeapWordSize) + _constants_size; + + _next_call_type = MARK_INVOKE_INVALID; +} + +// perform data and call relocation on the CodeBuffer +void CodeInstaller::initialize_buffer(CodeBuffer& buffer) { + int locs_buffer_size = _sites->length() * (relocInfo::length_limit + sizeof(relocInfo)); + char* locs_buffer = NEW_RESOURCE_ARRAY(char, locs_buffer_size); + buffer.insts()->initialize_shared_locs((relocInfo*)locs_buffer, locs_buffer_size / sizeof(relocInfo)); + buffer.initialize_stubs_size(256); + buffer.initialize_consts_size(_constants_size); + + _oop_recorder = new OopRecorder(_env->arena()); + _env->set_oop_recorder(_oop_recorder); + _debug_recorder = new DebugInformationRecorder(_env->oop_recorder()); + _debug_recorder->set_oopmaps(new OopMapSet()); + _dependencies = new Dependencies(_env); + + _env->set_oop_recorder(_oop_recorder); + _env->set_debug_info(_debug_recorder); + _env->set_dependencies(_dependencies); + buffer.initialize_oop_recorder(_oop_recorder); + + _instructions = buffer.insts(); + _constants = buffer.consts(); + + // copy the code into the newly created CodeBuffer + memcpy(_instructions->start(), _code->base(T_BYTE), _code_size); + _instructions->set_end(_instructions->start() + _code_size); + + oop* sites = (oop*) _sites->base(T_OBJECT); + for (int i = 0; i < _sites->length(); i++) { + oop site = sites[i]; + jint pc_offset = CiTargetMethod_Site::pcOffset(site); + + if (site->is_a(CiTargetMethod_Safepoint::klass())) { + TRACE_C1X_4("safepoint at %i", pc_offset); + site_Safepoint(buffer, pc_offset, site); + } else if (site->is_a(CiTargetMethod_Call::klass())) { + TRACE_C1X_4("call at %i", pc_offset); + site_Call(buffer, pc_offset, site); + } else if (site->is_a(CiTargetMethod_DataPatch::klass())) { + TRACE_C1X_4("datapatch at %i", pc_offset); + site_DataPatch(buffer, pc_offset, site); + } else if (site->is_a(CiTargetMethod_Mark::klass())) { + TRACE_C1X_4("mark at %i", pc_offset); + site_Mark(buffer, pc_offset, site); + } else { + fatal("unexpected Site subclass"); + } + } + + + if (_assumptions != NULL) { + oop* assumptions = (oop*) _assumptions->base(T_OBJECT); + for (int i = 0; i < _assumptions->length(); ++i) { + oop assumption = assumptions[i]; + if (assumption != NULL) { + if (assumption->is_a(CiAssumptions_ConcreteSubtype::klass())) { + assumption_ConcreteSubtype(assumption); + } else if (assumption->is_a(CiAssumptions_ConcreteMethod::klass())) { + assumption_ConcreteMethod(assumption); + } else { + fatal("unexpected Assumption subclass"); + } + } + } + } +} + +void CodeInstaller::assumption_ConcreteSubtype(oop assumption) { + oop context_oop = CiAssumptions_ConcreteSubtype::context(assumption); + oop type_oop = CiAssumptions_ConcreteSubtype::subtype(assumption); + + ciKlass* context = (ciKlass*) CURRENT_ENV->get_object(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(context_oop))); + ciKlass* type = (ciKlass*) CURRENT_ENV->get_object(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type_oop))); + + _dependencies->assert_leaf_type(type); + if (context != type) { + assert(context->is_abstract(), ""); + ThreadToNativeFromVM trans(JavaThread::current()); + _dependencies->assert_abstract_with_unique_concrete_subtype(context, type); + } +} + +void CodeInstaller::assumption_ConcreteMethod(oop assumption) { + oop context_oop = CiAssumptions_ConcreteMethod::context(assumption); + oop method_oop = CiAssumptions_ConcreteMethod::method(assumption); + jlong context_oop_id = HotSpotMethodResolved::vmId(context_oop); + jlong method_oop_id = HotSpotMethodResolved::vmId(method_oop); + methodOop method = VmIds::get(method_oop_id); + methodOop context = VmIds::get(context_oop_id); + + ciMethod* m = (ciMethod*) CURRENT_ENV->get_object(method); + ciMethod* c = (ciMethod*) CURRENT_ENV->get_object(context); + ciKlass* context_klass = c->holder(); + { + ThreadToNativeFromVM trans(JavaThread::current()); + _dependencies->assert_unique_concrete_method(context_klass, m); + } +} + +void CodeInstaller::process_exception_handlers() { + // allocate some arrays for use by the collection code. + const int num_handlers = 5; + GrowableArray* bcis = new GrowableArray (num_handlers); + GrowableArray* scope_depths = new GrowableArray (num_handlers); + GrowableArray* pcos = new GrowableArray (num_handlers); + + if (_exception_handlers != NULL) { + oop* exception_handlers = (oop*) _exception_handlers->base(T_OBJECT); + for (int i = 0; i < _exception_handlers->length(); i++) { + jint pc_offset = CiTargetMethod_Site::pcOffset(exception_handlers[i]); + int start = i; + while ((i + 1) < _exception_handlers->length() && CiTargetMethod_Site::pcOffset(exception_handlers[i + 1]) == pc_offset) + i++; + + // empty the arrays + bcis->trunc_to(0); + scope_depths->trunc_to(0); + pcos->trunc_to(0); + + for (int j = start; j <= i; j++) { + oop exc = exception_handlers[j]; + jint handler_offset = CiTargetMethod_ExceptionHandler::handlerPos(exc); + jint handler_bci = CiTargetMethod_ExceptionHandler::handlerBci(exc); + jint bci = CiTargetMethod_ExceptionHandler::bci(exc); + jint scope_level = CiTargetMethod_ExceptionHandler::scopeLevel(exc); + Handle handler_type = CiTargetMethod_ExceptionHandler::exceptionType(exc); + + assert(handler_offset != -1, "must have been generated"); + + int e = bcis->find(handler_bci); + if (e >= 0 && scope_depths->at(e) == scope_level) { + // two different handlers are declared to dispatch to the same + // catch bci. During parsing we created edges for each + // handler but we really only need one. The exception handler + // table will also get unhappy if we try to declare both since + // it's nonsensical. Just skip this handler. + continue; + } + + bcis->append(handler_bci); + if (handler_bci == -1) { + // insert a wildcard handler at scope depth 0 so that the + // exception lookup logic with find it. + scope_depths->append(0); + } else { + scope_depths->append(scope_level); + } + pcos->append(handler_offset); + + // stop processing once we hit a catch any + // if (handler->is_catch_all()) { + // assert(i == handlers->length() - 1, "catch all must be last handler"); + // } + + } + _exception_handler_table.add_subtable(pc_offset, bcis, scope_depths, pcos); + } + } + +} + +void CodeInstaller::record_scope(jint pc_offset, oop code_pos) { + oop caller_pos = CiCodePos::caller(code_pos); + if (caller_pos != NULL) { + record_scope(pc_offset, caller_pos); + } + oop frame = NULL; + if (code_pos->klass()->klass_part()->name() == vmSymbols::com_sun_cri_ci_CiFrame()) { + frame = code_pos; + } + + oop hotspot_method = CiCodePos::method(code_pos); + assert(hotspot_method != NULL && hotspot_method->is_a(HotSpotMethodResolved::klass()), "unexpected hotspot method"); + methodOop method = VmIds::get(HotSpotMethodResolved::vmId(hotspot_method)); + ciMethod *cimethod = (ciMethod *) _env->get_object(method); + jint bci = CiCodePos::bci(code_pos); + bool reexecute; + if (bci == -1) { + reexecute = false; + } else { + Bytecodes::Code code = Bytecodes::java_code_at(method, method->bcp_from(bci)); + reexecute = Interpreter::bytecode_should_reexecute(code); + } + + if (TraceC1X >= 2) { + tty->print_cr("Recording scope pc_offset=%d bci=%d frame=%d", pc_offset, bci, frame); + } + + if (frame != NULL) { + jint local_count = CiFrame::numLocals(frame); + jint expression_count = CiFrame::numStack(frame); + jint monitor_count = CiFrame::numLocks(frame); + arrayOop values = (arrayOop) CiFrame::values(frame); + + assert(local_count + expression_count + monitor_count == values->length(), "unexpected values length"); + + GrowableArray* locals = new GrowableArray (); + GrowableArray* expressions = new GrowableArray (); + GrowableArray* monitors = new GrowableArray (); + + if (TraceC1X >= 2) { + tty->print_cr("Scope at bci %d with %d values", bci, values->length()); + tty->print_cr("%d locals %d expressions, %d monitors", local_count, expression_count, monitor_count); + } + + for (jint i = 0; i < values->length(); i++) { + ScopeValue* value = get_hotspot_value(((oop*) values->base(T_OBJECT))[i], _frame_size); + + if (i < local_count) { + locals->append(value); + } else if (i < local_count + expression_count) { + expressions->append(value); + } else { + assert(value->is_location(), "invalid monitor location"); + LocationValue* loc = (LocationValue*)value; + int monitor_offset = loc->location().stack_offset(); + LocationValue* obj = new LocationValue(Location::new_stk_loc(Location::oop, monitor_offset + BasicObjectLock::obj_offset_in_bytes())); + monitors->append(new MonitorValue(obj, Location::new_stk_loc(Location::normal, monitor_offset + BasicObjectLock::lock_offset_in_bytes()))); + } + } + DebugToken* locals_token = _debug_recorder->create_scope_values(locals); + DebugToken* expressions_token = _debug_recorder->create_scope_values(expressions); + DebugToken* monitors_token = _debug_recorder->create_monitor_values(monitors); + + _debug_recorder->describe_scope(pc_offset, cimethod, bci, reexecute, false, false, locals_token, expressions_token, monitors_token); + } else { + _debug_recorder->describe_scope(pc_offset, cimethod, bci, reexecute, false, false, NULL, NULL, NULL); + } +} + +void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site) { + oop debug_info = CiTargetMethod_Safepoint::debugInfo(site); + assert(debug_info != NULL, "debug info expected"); + + // address instruction = _instructions->start() + pc_offset; + // jint next_pc_offset = Assembler::locate_next_instruction(instruction) - _instructions->start(); + _debug_recorder->add_safepoint(pc_offset, create_oop_map(_frame_size, _parameter_count, debug_info)); + + oop code_pos = CiDebugInfo::codePos(debug_info); + record_scope(pc_offset, code_pos); + + _debug_recorder->end_safepoint(pc_offset); +} + +void CodeInstaller::site_Call(CodeBuffer& buffer, jint pc_offset, oop site) { + oop runtime_call = CiTargetMethod_Call::runtimeCall(site); + oop hotspot_method = CiTargetMethod_Call::method(site); + oop symbol = CiTargetMethod_Call::symbol(site); + oop global_stub = CiTargetMethod_Call::globalStubID(site); + + oop debug_info = CiTargetMethod_Call::debugInfo(site); + + assert((runtime_call ? 1 : 0) + (hotspot_method ? 1 : 0) + (symbol ? 1 : 0) + (global_stub ? 1 : 0) == 1, "Call site needs exactly one type"); + + assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size)"); + jint next_pc_offset = pc_offset + NativeCall::instruction_size; + + if (debug_info != NULL) { + _debug_recorder->add_safepoint(next_pc_offset, create_oop_map(_frame_size, _parameter_count, debug_info)); + oop code_pos = CiDebugInfo::codePos(debug_info); + record_scope(next_pc_offset, code_pos); + } + + if (runtime_call != NULL) { + NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); + if (runtime_call == CiRuntimeCall::Debug()) { + TRACE_C1X_3("CiRuntimeCall::Debug()"); + } else if (runtime_call == CiRuntimeCall::UnwindException()) { + call->set_destination(Runtime1::entry_for(Runtime1::c1x_unwind_exception_call_id)); + _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); + TRACE_C1X_3("CiRuntimeCall::UnwindException()"); + } else if (runtime_call == CiRuntimeCall::HandleException()) { + call->set_destination(Runtime1::entry_for(Runtime1::c1x_handle_exception_id)); + _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); + TRACE_C1X_3("CiRuntimeCall::HandleException()"); + } else if (runtime_call == CiRuntimeCall::JavaTimeMillis()) { + call->set_destination((address)os::javaTimeMillis); + _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); + TRACE_C1X_3("CiRuntimeCall::JavaTimeMillis()"); + } else if (runtime_call == CiRuntimeCall::JavaTimeNanos()) { + call->set_destination((address)os::javaTimeNanos); + _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); + TRACE_C1X_3("CiRuntimeCall::JavaTimeNanos()"); + } else if (runtime_call == CiRuntimeCall::ArithmeticFrem()) { + call->set_destination(Runtime1::entry_for(Runtime1::c1x_arithmetic_frem_id)); + _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); + TRACE_C1X_3("CiRuntimeCall::ArithmeticFrem()"); + } else if (runtime_call == CiRuntimeCall::ArithmeticDrem()) { + call->set_destination(Runtime1::entry_for(Runtime1::c1x_arithmetic_drem_id)); + _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); + TRACE_C1X_3("CiRuntimeCall::ArithmeticDrem()"); + } else if (runtime_call == CiRuntimeCall::RegisterFinalizer()) { + call->set_destination(Runtime1::entry_for(Runtime1::register_finalizer_id)); + _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); + } else if (runtime_call == CiRuntimeCall::Deoptimize()) { + call->set_destination(SharedRuntime::deopt_blob()->uncommon_trap()); + _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); + } else { + runtime_call->print(); + fatal("runtime_call not implemented"); + } + } else if (global_stub != NULL) { + NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset); + assert(java_lang_boxing_object::is_instance(global_stub, T_LONG), "global_stub needs to be of type Long"); + + if (inst->is_call()) { + nativeCall_at((address)inst)->set_destination(VmIds::getStub(global_stub)); + } else { + nativeJump_at((address)inst)->set_jump_destination(VmIds::getStub(global_stub)); + } + _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand); + TRACE_C1X_3("relocating (stub) at %016x", inst); + } else if (symbol != NULL) { + fatal("symbol"); + } else { // method != NULL + NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); + assert(hotspot_method != NULL, "unexpected RiMethod"); + assert(debug_info != NULL, "debug info expected"); + + methodOop method = NULL; + if (hotspot_method->is_a(HotSpotMethodResolved::klass())) method = VmIds::get(HotSpotMethodResolved::vmId(hotspot_method)); + + assert(debug_info != NULL, "debug info expected"); + + TRACE_C1X_3("method call"); + switch (_next_call_type) { + case MARK_INVOKEVIRTUAL: + case MARK_INVOKEINTERFACE: { + assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface"); + + call->set_destination(SharedRuntime::get_resolve_virtual_call_stub()); + _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc), Assembler::call32_operand); + break; + } + case MARK_INVOKESTATIC: { + assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic"); + call->set_destination(SharedRuntime::get_resolve_static_call_stub()); + _instructions->relocate(call->instruction_address(), relocInfo::static_call_type, Assembler::call32_operand); + break; + } + case MARK_INVOKESPECIAL: { + assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial"); + + call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub()); + _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type, Assembler::call32_operand); + break; + } + case MARK_INVOKE_INVALID: + default: + fatal("invalid _next_call_type value"); + break; + } + } + _next_call_type = MARK_INVOKE_INVALID; + if (debug_info != NULL) { + _debug_recorder->end_safepoint(next_pc_offset); + } +} + +void CodeInstaller::site_DataPatch(CodeBuffer& buffer, jint pc_offset, oop site) { + oop constant = CiTargetMethod_DataPatch::constant(site); + oop kind = CiConstant::kind(constant); + + address instruction = _instructions->start() + pc_offset; + + char typeChar = CiKind::typeChar(kind); + switch (typeChar) { + case 'z': + case 'b': + case 's': + case 'c': + case 'i': + fatal("int-sized values not expected in DataPatch") + ; + break; + case 'f': + case 'l': + case 'd': { + address operand = Assembler::locate_operand(instruction, Assembler::disp32_operand); + address next_instruction = Assembler::locate_next_instruction(instruction); + // we don't care if this is a long/double/etc., the primitive field contains the right bits + int size = _constants->size(); + if (typeChar == 'd' || typeChar == 'l') { + size = _constants->align_at_start(size); + } + address dest = _constants->start() + size; + _constants->set_end(dest + BytesPerLong); + *(jlong*) dest = CiConstant::primitive(constant); + + long disp = dest - next_instruction; + assert(disp == (jint) disp, "disp doesn't fit in 32 bits"); + *((jint*) operand) = (jint) disp; + + _instructions->relocate(instruction, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand); + TRACE_C1X_3("relocating (%c) at %016x/%016x with destination at %016x (%d)", typeChar, instruction, operand, dest, size); + break; + } + case 'a': { + address operand = Assembler::locate_operand(instruction, Assembler::imm_operand); + Handle obj = CiConstant::object(constant); + + if (obj->is_a(HotSpotTypeResolved::klass())) { + assert(!obj.is_null(), ""); + *((jobject*) operand) = JNIHandles::make_local(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(obj))); + _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); + TRACE_C1X_3("relocating (HotSpotType) at %016x/%016x", instruction, operand); + } else { + jobject value; + if (obj() == HotSpotProxy::DUMMY_CONSTANT_OBJ()) { + value = (jobject) Universe::non_oop_word(); + } else { + value = JNIHandles::make_local(obj()); + } + *((jobject*) operand) = value; + _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); + TRACE_C1X_3("relocating (oop constant) at %016x/%016x", instruction, operand); + } + break; + } + default: + fatal("unexpected CiKind in DataPatch"); + break; + } +} + +void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, oop site) { + oop id_obj = CiTargetMethod_Mark::id(site); + arrayOop references = (arrayOop) CiTargetMethod_Mark::references(site); + + if (id_obj != NULL) { + assert(java_lang_boxing_object::is_instance(id_obj, T_INT), "Integer id expected"); + jint id = id_obj->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT)); + + address instruction = _instructions->start() + pc_offset; + + switch (id) { + case MARK_UNVERIFIED_ENTRY: + _offsets.set_value(CodeOffsets::Entry, pc_offset); + break; + case MARK_VERIFIED_ENTRY: + _offsets.set_value(CodeOffsets::Verified_Entry, pc_offset); + break; + case MARK_OSR_ENTRY: + _offsets.set_value(CodeOffsets::OSR_Entry, pc_offset); + break; + case MARK_UNWIND_ENTRY: + _offsets.set_value(CodeOffsets::UnwindHandler, pc_offset); + break; + case MARK_EXCEPTION_HANDLER_ENTRY: + _offsets.set_value(CodeOffsets::Exceptions, pc_offset); + break; + case MARK_DEOPT_HANDLER_ENTRY: + _offsets.set_value(CodeOffsets::Deopt, pc_offset); + break; + case MARK_STATIC_CALL_STUB: { + assert(references->length() == 1, "static call stub needs one reference"); + oop ref = ((oop*) references->base(T_OBJECT))[0]; + address call_pc = _instructions->start() + CiTargetMethod_Site::pcOffset(ref); + _instructions->relocate(instruction, static_stub_Relocation::spec(call_pc)); + _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); + break; + } + case MARK_INVOKE_INVALID: + case MARK_INVOKEINTERFACE: + case MARK_INVOKESTATIC: + case MARK_INVOKESPECIAL: + case MARK_INVOKEVIRTUAL: + _next_call_type = (MarkId) id; + _invoke_mark_pc = instruction; + break; + case MARK_IMPLICIT_NULL: + _implicit_exception_table.append(pc_offset, pc_offset); + break; + case MARK_KLASS_PATCHING: + case MARK_ACCESS_FIELD_PATCHING: { + unsigned char* byte_count = (unsigned char*) (instruction - 1); + unsigned char* byte_skip = (unsigned char*) (instruction - 2); + unsigned char* being_initialized_entry_offset = (unsigned char*) (instruction - 3); + + assert(*byte_skip == 5, "unexpected byte_skip"); + + assert(references->length() == 2, "MARK_KLASS_PATCHING/MARK_ACCESS_FIELD_PATCHING needs 2 references"); + oop ref1 = ((oop*) references->base(T_OBJECT))[0]; + oop ref2 = ((oop*) references->base(T_OBJECT))[1]; + int i_byte_count = CiTargetMethod_Site::pcOffset(ref2) - CiTargetMethod_Site::pcOffset(ref1); + assert(i_byte_count == (unsigned char)i_byte_count, "invalid offset"); + *byte_count = i_byte_count; + *being_initialized_entry_offset = *byte_count + *byte_skip; + + // we need to correct the offset of a field access - it's created with MAX_INT to ensure the correct size, and hotspot expects 0 + if (id == MARK_ACCESS_FIELD_PATCHING) { + NativeMovRegMem* inst = nativeMovRegMem_at(_instructions->start() + CiTargetMethod_Site::pcOffset(ref1)); + assert(inst->offset() == max_jint, "unexpected offset value"); + inst->set_offset(0); + } + break; + } + case MARK_DUMMY_OOP_RELOCATION: { + _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); + + RelocIterator iter(_instructions, (address) instruction, (address) (instruction + 1)); + relocInfo::change_reloc_info_for_address(&iter, (address) instruction, relocInfo::oop_type, relocInfo::none); + break; + } + default: + ShouldNotReachHere(); + break; + } + } +} + diff -r 2fb867285938 -r c23d45daff9b src/share/vm/graal/graalCodeInstaller.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalCodeInstaller.hpp Wed Jun 08 13:40:25 2011 +0200 @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2011, 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. + */ + +/* + * This class handles the conversion from a CiTargetMethod to a CodeBlob or an nmethod. + */ +class CodeInstaller { +private: + // these need to correspond to HotSpotXirGenerator.java + enum MarkId { + MARK_VERIFIED_ENTRY = 0x0001, + MARK_UNVERIFIED_ENTRY = 0x0002, + MARK_OSR_ENTRY = 0x0003, + MARK_UNWIND_ENTRY = 0x0004, + MARK_EXCEPTION_HANDLER_ENTRY = 0x0005, + MARK_DEOPT_HANDLER_ENTRY = 0x0006, + MARK_STATIC_CALL_STUB = 0x1000, + MARK_INVOKE_INVALID = 0x2000, + MARK_INVOKEINTERFACE = 0x2001, + MARK_INVOKESTATIC = 0x2002, + MARK_INVOKESPECIAL = 0x2003, + MARK_INVOKEVIRTUAL = 0x2004, + MARK_IMPLICIT_NULL = 0x3000, + MARK_KLASS_PATCHING = 0x4000, + MARK_DUMMY_OOP_RELOCATION = 0x4001, + MARK_ACCESS_FIELD_PATCHING = 0x4002 + }; + + ciEnv* _env; + + oop _citarget_method; + oop _hotspot_method; + oop _name; + arrayOop _sites; + arrayOop _assumptions; + arrayOop _exception_handlers; + CodeOffsets _offsets; + + arrayOop _code; + jint _code_size; + jint _frame_size; + jint _custom_stack_area_offset; + jint _parameter_count; + jint _constants_size; + jint _total_size; + + MarkId _next_call_type; + address _invoke_mark_pc; + + CodeSection* _instructions; + CodeSection* _constants; + + OopRecorder* _oop_recorder; + DebugInformationRecorder* _debug_recorder; + Dependencies* _dependencies; + ExceptionHandlerTable _exception_handler_table; + ImplicitExceptionTable _implicit_exception_table; + +public: + + // constructor used to create a method + CodeInstaller(Handle target_method); + + // constructor used to create a stub + CodeInstaller(Handle target_method, jlong& id); + +private: + // extract the fields of the CiTargetMethod + void initialize_fields(Handle target_method); + + // perform data and call relocation on the CodeBuffer + void initialize_buffer(CodeBuffer& buffer); + + void assumption_ConcreteSubtype(oop assumption); + void assumption_ConcreteMethod(oop assumption); + + void site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site); + void site_Call(CodeBuffer& buffer, jint pc_offset, oop site); + void site_DataPatch(CodeBuffer& buffer, jint pc_offset, oop site); + void site_Mark(CodeBuffer& buffer, jint pc_offset, oop site); + + void record_scope(jint pc_offset, oop code_pos); + + void process_exception_handlers(); + +}; diff -r 2fb867285938 -r c23d45daff9b src/share/vm/graal/graalCompiler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalCompiler.cpp Wed Jun 08 13:40:25 2011 +0200 @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2011, 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. + */ + +#include "precompiled.hpp" +#include "c1x/c1x_Compiler.hpp" +#include "c1x/c1x_JavaAccess.hpp" +#include "c1x/c1x_VMExits.hpp" +#include "c1x/c1x_VMEntries.hpp" +#include "c1x/c1x_VmIds.hpp" +#include "c1/c1_Runtime1.hpp" +#include "runtime/arguments.hpp" + +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"); + + VmIds::initializeObjects(); + + initialize_buffer_blob(); + Runtime1::initialize(THREAD->get_buffer_blob()); + + JNIEnv *env = ((JavaThread *) Thread::current())->jni_environment(); + jclass klass = env->FindClass("com/oracle/max/graal/runtime/VMEntriesNative"); + if (klass == NULL) { + tty->print_cr("c1x VMEntries class not found"); + vm_abort(false); + } + 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; + VMExits::setDefaultOptions(); + 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); + jboolean result = VMExits::setOption(option); + if (!result) { + tty->print_cr("Invalid option for C1X!"); + vm_abort(false); + } + } + + VMExits::initializeCompiler(); + } +} + +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(); + + TRACE_C1X_2("C1XCompiler::compile_method"); + + CompilerThread::current()->set_compiling(true); + methodOop method = (methodOop) target->get_oop(); + VMExits::compileMethod(VmIds::add(method), VmIds::toString(method->name(), THREAD), entry_bci); + CompilerThread::current()->set_compiling(false); + + VmIds::cleanupLocalObjects(); + TRACE_C1X_2("C1XCompiler::compile_method exit"); +} + +// 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(klass->name(), THREAD); + return createHotSpotTypeResolved(klass, name, CHECK_NULL); + } else { + Symbol* name = ((ciKlass *) type)->name()->get_symbol(); + return VMExits::createRiTypeUnresolved(VmIds::toString(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(field->name()->get_symbol(), CHECK_0); + Handle field_holder = get_RiType(field->holder(), accessor, CHECK_0); + Handle field_type = get_RiType(field->type(), accessor, CHECK_0); + int flags = field->flags().as_int(); + return VMExits::createRiField(field_holder, field_name, field_type, offset, flags, 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); + Handle obj = instanceKlass::cast(HotSpotTypeResolved::klass())->allocate_instance(CHECK_NULL); + assert(obj() != NULL, "must succeed in allocating instance"); + + HotSpotTypeResolved::set_compiler(obj, VMExits::compilerInstance()()); + + if (klass->oop_is_instance()) { + instanceKlass* ik = (instanceKlass*)klass()->klass_part(); + Handle full_name = java_lang_String::create_from_str(ik->signature_name(), CHECK_NULL); + HotSpotType::set_name(obj, full_name()); + } else { + HotSpotType::set_name(obj, name()); + } + + HotSpotTypeResolved::set_javaMirror(obj, klass->java_mirror()); + HotSpotTypeResolved::set_simpleName(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; + } + return T_ILLEGAL; +} + diff -r 2fb867285938 -r c23d45daff9b src/share/vm/graal/graalCompiler.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalCompiler.hpp Wed Jun 08 13:40:25 2011 +0200 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2011, 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. + */ + +#include "compiler/abstractCompiler.hpp" + +class C1XCompiler : public AbstractCompiler { + +private: + + bool _initialized; + + static C1XCompiler* _instance; + +public: + + C1XCompiler(); + + static C1XCompiler* instance() { return _instance; } + + + virtual const char* name() { return "C1X"; } + + // Native / OSR not supported + virtual bool supports_native() { return false; } + virtual bool supports_osr () { return false; } + + // Pretend to be C1 + bool is_c1 () { return true; } + bool is_c2 () { return false; } + + // Initialization + virtual void initialize(); + + // Compilation entry point for methods + virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci); + + // Print compilation timers and statistics + virtual void print_timers(); + + static oop get_RiType(ciType *klass, KlassHandle accessor, TRAPS); + static oop get_RiField(ciField *ciField, ciInstanceKlass* accessor_klass, KlassHandle accessor, Bytecodes::Code byteCode, TRAPS); + + static oop createHotSpotTypeResolved(KlassHandle klass, Handle name, TRAPS); + + static BasicType kindToBasicType(jchar ch); + + static int to_cp_index_u2(int index) { + // Swap. + index = ((index & 0xFF) << 8) | (index >> 8); + // Tag. + index = index + constantPoolOopDesc::CPCACHE_INDEX_TAG; + return index; + } + +private: + + void initialize_buffer_blob(); +}; + +// Tracing macros + +#define IF_TRACE_C1X_1 if (!(TraceC1X >= 1)) ; else +#define IF_TRACE_C1X_2 if (!(TraceC1X >= 2)) ; else +#define IF_TRACE_C1X_3 if (!(TraceC1X >= 3)) ; else +#define IF_TRACE_C1X_4 if (!(TraceC1X >= 4)) ; else +#define IF_TRACE_C1X_5 if (!(TraceC1X >= 5)) ; else + +// using commas and else to keep one-instruction semantics + +#define TRACE_C1X_1 if (!(TraceC1X >= 1 && (tty->print("TraceC1X-1: "), true))) ; else tty->print_cr +#define TRACE_C1X_2 if (!(TraceC1X >= 2 && (tty->print(" TraceC1X-2: "), true))) ; else tty->print_cr +#define TRACE_C1X_3 if (!(TraceC1X >= 3 && (tty->print(" TraceC1X-3: "), true))) ; else tty->print_cr +#define TRACE_C1X_4 if (!(TraceC1X >= 4 && (tty->print(" TraceC1X-4: "), true))) ; else tty->print_cr +#define TRACE_C1X_5 if (!(TraceC1X >= 5 && (tty->print(" TraceC1X-5: "), true))) ; else tty->print_cr + + + diff -r 2fb867285938 -r c23d45daff9b src/share/vm/graal/graalJavaAccess.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalJavaAccess.cpp Wed Jun 08 13:40:25 2011 +0200 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2011, 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. + */ + +#include "precompiled.hpp" +#include "c1x/c1x_JavaAccess.hpp" +#include "runtime/jniHandles.hpp" +#include "classfile/symbolTable.hpp" +// This function is similar to javaClasses.cpp, it computes the field offset of a (static or instance) field. +// It looks up the name and signature symbols without creating new ones, all the symbols of these classes need to be already loaded. + +static void compute_offset(int &dest_offset, klassOop klass_oop, const char* name, const char* signature, bool static_field) { + Symbol* name_symbol = SymbolTable::probe(name, (int)strlen(name)); + Symbol* signature_symbol = SymbolTable::probe(signature, (int)strlen(signature)); +#ifdef DEBUG + if (name_symbol == NULL) { + tty->print_cr("symbol with name %s was not found in symbol table (klass=%s)", name, klass_oop->klass_part()->name()->as_C_string()); + } +#endif + assert(name_symbol != NULL, "symbol not found - class layout changed?"); + assert(signature_symbol != NULL, "symbol not found - class layout changed?"); + + instanceKlass* ik = instanceKlass::cast(klass_oop); + fieldDescriptor fd; + if (!ik->find_field(name_symbol, signature_symbol, &fd)) { + ResourceMark rm; + tty->print_cr("Invalid layout of %s at %s", name_symbol->as_C_string(), ik->external_name()); + fatal("Invalid layout of preloaded class"); + } + assert(fd.is_static() == static_field, "static/instance mismatch"); + dest_offset = fd.offset(); +} + +// This piece of macro magic creates the contents of the c1x_compute_offsets method that initializes the field indices of all the access classes. + +#define START_CLASS(name) { klassOop k = SystemDictionary::name##_klass(); assert(k != NULL, "Could not find class " #name ""); + +#define END_CLASS } + +#define FIELD(klass, name, signature, static_field) compute_offset(klass::_##name##_offset, k, #name, signature, static_field); +#define CHAR_FIELD(klass, name) FIELD(klass, name, "C", false) +#define INT_FIELD(klass, name) FIELD(klass, name, "I", false) +#define BOOLEAN_FIELD(klass, name) FIELD(klass, name, "Z", false) +#define LONG_FIELD(klass, name) FIELD(klass, name, "J", false) +#define OOP_FIELD(klass, name, signature) FIELD(klass, name, signature, false) +#define STATIC_OOP_FIELD(klass, name, signature) FIELD(klass, name, signature, true) + + +void c1x_compute_offsets() { + COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, OOP_FIELD, STATIC_OOP_FIELD) +} + +#define EMPTY0 +#define EMPTY1(x) +#define EMPTY2(x,y) +#define FIELD2(klass, name) int klass::_##name##_offset = 0; +#define FIELD3(klass, name, sig) FIELD2(klass, name) + +COMPILER_CLASSES_DO(EMPTY1, EMPTY0, FIELD2, FIELD2, FIELD2, FIELD2, FIELD3, FIELD3) + + + + + diff -r 2fb867285938 -r c23d45daff9b src/share/vm/graal/graalJavaAccess.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalJavaAccess.hpp Wed Jun 08 13:40:25 2011 +0200 @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2011, 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. + */ + +void c1x_compute_offsets(); + +#include "classfile/systemDictionary.hpp" +#include "oops/instanceMirrorKlass.hpp" + +/* This macro defines the structure of the CiTargetMethod - classes. + * It will generate classes with accessors similar to javaClasses.hpp, but with specializations for oops, Handles and jni handles. + * + * The public interface of these classes will look like this: + + * class CiStackSlot : AllStatic { + * public: + * static klassOop klass(); + * static jint index(oop obj); + * static jint index(Handle obj); + * static jint index(jobject obj); + * static void set_index(oop obj, jint x); + * static void set_index(Handle obj, jint x); + * static void set_index(jobject obj, jint x); + * }; + * + */ + +#define COMPILER_CLASSES_DO(start_class, end_class, char_field, int_field, boolean_field, long_field, oop_field, static_oop_field) \ + start_class(HotSpotTypeResolved) \ + oop_field(HotSpotTypeResolved, compiler, "Lcom/oracle/max/graal/runtime/Compiler;") \ + oop_field(HotSpotTypeResolved, javaMirror, "Ljava/lang/Class;") \ + oop_field(HotSpotTypeResolved, simpleName, "Ljava/lang/String;") \ + int_field(HotSpotTypeResolved, accessFlags) \ + boolean_field(HotSpotTypeResolved, hasFinalizer) \ + boolean_field(HotSpotTypeResolved, hasSubclass) \ + boolean_field(HotSpotTypeResolved, hasFinalizableSubclass) \ + boolean_field(HotSpotTypeResolved, isInitialized) \ + boolean_field(HotSpotTypeResolved, isArrayClass) \ + boolean_field(HotSpotTypeResolved, isInstanceClass) \ + boolean_field(HotSpotTypeResolved, isInterface) \ + int_field(HotSpotTypeResolved, instanceSize) \ + oop_field(HotSpotTypeResolved, componentType, "Lcom/sun/cri/ri/RiType;") \ + end_class \ + start_class(HotSpotType) \ + oop_field(HotSpotType, name, "Ljava/lang/String;") \ + end_class \ + start_class(HotSpotField) \ + oop_field(HotSpotField, constant, "Lcom/sun/cri/ci/CiConstant;") \ + end_class \ + start_class(HotSpotMethodResolved) \ + long_field(HotSpotMethodResolved, vmId) \ + end_class \ + start_class(HotSpotProxy) \ + static_oop_field(HotSpotProxy, DUMMY_CONSTANT_OBJ, "Ljava/lang/Long;") \ + end_class \ + start_class(HotSpotTargetMethod) \ + oop_field(HotSpotTargetMethod, targetMethod, "Lcom/sun/cri/ci/CiTargetMethod;") \ + oop_field(HotSpotTargetMethod, method, "Lcom/oracle/max/graal/runtime/HotSpotMethodResolved;") \ + oop_field(HotSpotTargetMethod, name, "Ljava/lang/String;") \ + oop_field(HotSpotTargetMethod, sites, "[Lcom/sun/cri/ci/CiTargetMethod$Site;") \ + oop_field(HotSpotTargetMethod, exceptionHandlers, "[Lcom/sun/cri/ci/CiTargetMethod$ExceptionHandler;") \ + end_class \ + start_class(HotSpotExceptionHandler) \ + int_field(HotSpotExceptionHandler, startBci) \ + int_field(HotSpotExceptionHandler, endBci) \ + int_field(HotSpotExceptionHandler, handlerBci) \ + int_field(HotSpotExceptionHandler, catchClassIndex) \ + oop_field(HotSpotExceptionHandler, catchClass, "Lcom/sun/cri/ri/RiType;") \ + end_class \ + start_class(CiTargetMethod) \ + int_field(CiTargetMethod, frameSize) \ + int_field(CiTargetMethod, customStackAreaOffset) \ + oop_field(CiTargetMethod, targetCode, "[B") \ + oop_field(CiTargetMethod, assumptions, "Lcom/sun/cri/ci/CiAssumptions;") \ + int_field(CiTargetMethod, targetCodeSize) \ + end_class \ + start_class(CiAssumptions) \ + oop_field(CiAssumptions, list, "[Lcom/sun/cri/ci/CiAssumptions$Assumption;") \ + end_class \ + start_class(CiAssumptions_ConcreteSubtype) \ + oop_field(CiAssumptions_ConcreteSubtype, context, "Lcom/sun/cri/ri/RiType;") \ + oop_field(CiAssumptions_ConcreteSubtype, subtype, "Lcom/sun/cri/ri/RiType;") \ + end_class \ + start_class(CiAssumptions_ConcreteMethod) \ + oop_field(CiAssumptions_ConcreteMethod, context, "Lcom/sun/cri/ri/RiMethod;") \ + oop_field(CiAssumptions_ConcreteMethod, method, "Lcom/sun/cri/ri/RiMethod;") \ + end_class \ + start_class(CiTargetMethod_Site) \ + int_field(CiTargetMethod_Site, pcOffset) \ + end_class \ + start_class(CiTargetMethod_Call) \ + oop_field(CiTargetMethod_Call, runtimeCall, "Lcom/sun/cri/ci/CiRuntimeCall;") \ + oop_field(CiTargetMethod_Call, method, "Lcom/sun/cri/ri/RiMethod;") \ + oop_field(CiTargetMethod_Call, symbol, "Ljava/lang/String;") \ + oop_field(CiTargetMethod_Call, globalStubID, "Ljava/lang/Object;") \ + oop_field(CiTargetMethod_Call, debugInfo, "Lcom/sun/cri/ci/CiDebugInfo;") \ + end_class \ + start_class(CiTargetMethod_DataPatch) \ + oop_field(CiTargetMethod_DataPatch, constant, "Lcom/sun/cri/ci/CiConstant;") \ + end_class \ + start_class(CiTargetMethod_Safepoint) \ + oop_field(CiTargetMethod_Safepoint, debugInfo, "Lcom/sun/cri/ci/CiDebugInfo;") \ + end_class \ + start_class(CiTargetMethod_ExceptionHandler) \ + int_field(CiTargetMethod_ExceptionHandler, handlerPos) \ + int_field(CiTargetMethod_ExceptionHandler, handlerBci) \ + int_field(CiTargetMethod_ExceptionHandler, bci) \ + int_field(CiTargetMethod_ExceptionHandler, scopeLevel) \ + oop_field(CiTargetMethod_ExceptionHandler, exceptionType, "Lcom/sun/cri/ri/RiType;")\ + end_class \ + start_class(CiTargetMethod_Mark) \ + oop_field(CiTargetMethod_Mark, id, "Ljava/lang/Object;") \ + oop_field(CiTargetMethod_Mark, references, "[Lcom/sun/cri/ci/CiTargetMethod$Mark;") \ + end_class \ + start_class(CiDebugInfo) \ + oop_field(CiDebugInfo, codePos, "Lcom/sun/cri/ci/CiCodePos;") \ + oop_field(CiDebugInfo, registerRefMap, "Lcom/sun/cri/ci/CiBitMap;") \ + oop_field(CiDebugInfo, frameRefMap, "Lcom/sun/cri/ci/CiBitMap;") \ + end_class \ + start_class(CiBitMap) \ + int_field(CiBitMap, size) \ + long_field(CiBitMap, low) \ + oop_field(CiBitMap, extra, "[J") \ + end_class \ + start_class(CiFrame) \ + oop_field(CiFrame, values, "[Lcom/sun/cri/ci/CiValue;") \ + int_field(CiFrame, numLocals) \ + int_field(CiFrame, numStack) \ + int_field(CiFrame, numLocks) \ + end_class \ + start_class(CiCodePos) \ + oop_field(CiCodePos, caller, "Lcom/sun/cri/ci/CiCodePos;") \ + oop_field(CiCodePos, method, "Lcom/sun/cri/ri/RiMethod;") \ + int_field(CiCodePos, bci) \ + end_class \ + start_class(CiConstant) \ + oop_field(CiConstant, kind, "Lcom/sun/cri/ci/CiKind;") \ + oop_field(CiConstant, object, "Ljava/lang/Object;") \ + long_field(CiConstant, primitive) \ + end_class \ + start_class(CiKind) \ + char_field(CiKind, typeChar) \ + static_oop_field(CiKind, Boolean, "Lcom/sun/cri/ci/CiKind;"); \ + static_oop_field(CiKind, Byte, "Lcom/sun/cri/ci/CiKind;"); \ + static_oop_field(CiKind, Char, "Lcom/sun/cri/ci/CiKind;"); \ + static_oop_field(CiKind, Short, "Lcom/sun/cri/ci/CiKind;"); \ + static_oop_field(CiKind, Int, "Lcom/sun/cri/ci/CiKind;"); \ + static_oop_field(CiKind, Long, "Lcom/sun/cri/ci/CiKind;"); \ + end_class \ + start_class(CiRuntimeCall) \ + static_oop_field(CiRuntimeCall, UnwindException, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ + static_oop_field(CiRuntimeCall, RegisterFinalizer, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ + static_oop_field(CiRuntimeCall, HandleException, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ + static_oop_field(CiRuntimeCall, OSRMigrationEnd, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ + static_oop_field(CiRuntimeCall, JavaTimeMillis, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ + static_oop_field(CiRuntimeCall, JavaTimeNanos, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ + static_oop_field(CiRuntimeCall, Debug, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ + static_oop_field(CiRuntimeCall, ArithmethicLrem, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ + static_oop_field(CiRuntimeCall, ArithmeticLdiv, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ + static_oop_field(CiRuntimeCall, ArithmeticFrem, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ + static_oop_field(CiRuntimeCall, ArithmeticDrem, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ + static_oop_field(CiRuntimeCall, ArithmeticCos, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ + static_oop_field(CiRuntimeCall, ArithmeticTan, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ + static_oop_field(CiRuntimeCall, ArithmeticLog, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ + static_oop_field(CiRuntimeCall, ArithmeticLog10, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ + static_oop_field(CiRuntimeCall, ArithmeticSin, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ + static_oop_field(CiRuntimeCall, Deoptimize, "Lcom/sun/cri/ci/CiRuntimeCall;"); \ + end_class \ + start_class(RiMethod) \ + end_class \ + start_class(CiValue) \ + oop_field(CiValue, kind, "Lcom/sun/cri/ci/CiKind;") \ + static_oop_field(CiValue, IllegalValue, "Lcom/sun/cri/ci/CiValue;"); \ + end_class \ + start_class(CiRegisterValue) \ + oop_field(CiRegisterValue, reg, "Lcom/sun/cri/ci/CiRegister;") \ + end_class \ + start_class(CiRegister) \ + int_field(CiRegister, number) \ + end_class \ + start_class(CiStackSlot) \ + int_field(CiStackSlot, index) \ + end_class \ + /* end*/ + + + + +#define START_CLASS(name) \ + class name : AllStatic { \ + private: \ + friend class C1XCompiler; \ + static void check(oop obj) { assert(obj != NULL, "NULL field access of class " #name); assert(obj->is_a(SystemDictionary::name##_klass()), "wrong class, " #name " expected"); } \ + static void compute_offsets(); \ + public: \ + static klassOop klass() { return SystemDictionary::name##_klass(); } + +#define END_CLASS }; + +#define FIELD(name, type, accessor) \ + static int _##name##_offset; \ + static type name(oop obj) { check(obj); return obj->accessor(_##name##_offset); } \ + static type name(Handle obj) { check(obj()); return obj->accessor(_##name##_offset); } \ + static type name(jobject obj) { check(JNIHandles::resolve(obj)); return JNIHandles::resolve(obj)->accessor(_##name##_offset); } \ + static void set_##name(oop obj, type x) { check(obj); obj->accessor##_put(_##name##_offset, x); } \ + static void set_##name(Handle obj, type x) { check(obj()); obj->accessor##_put(_##name##_offset, x); } \ + static void set_##name(jobject obj, type x) { check(JNIHandles::resolve(obj)); JNIHandles::resolve(obj)->accessor##_put(_##name##_offset, x); } + +#define CHAR_FIELD(klass, name) FIELD(name, jchar, char_field) +#define INT_FIELD(klass, name) FIELD(name, jint, int_field) +#define BOOLEAN_FIELD(klass, name) FIELD(name, jboolean, bool_field) +#define LONG_FIELD(klass, name) FIELD(name, jlong, long_field) +#define OOP_FIELD(klass, name, signature) FIELD(name, oop, obj_field) +#define STATIC_OOP_FIELD(klassName, name, signature) \ + static int _##name##_offset; \ + static oop name() { \ + instanceKlass* ik = instanceKlass::cast(klassName::klass()); \ + address addr = ik->static_field_addr(_##name##_offset - instanceMirrorKlass::offset_of_static_fields()); \ + if (UseCompressedOops) { \ + return oopDesc::load_decode_heap_oop((narrowOop *)addr); \ + } else { \ + return oopDesc::load_decode_heap_oop((oop*)addr); \ + } \ + } \ + static void set_##name(oop x) { \ + instanceKlass* ik = instanceKlass::cast(klassName::klass()); \ + address addr = ik->static_field_addr(_##name##_offset - instanceMirrorKlass::offset_of_static_fields()); \ + if (UseCompressedOops) { \ + oopDesc::encode_store_heap_oop((narrowOop *)addr, x); \ + } else { \ + oopDesc::encode_store_heap_oop((oop*)addr, x); \ + } \ + } +COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, OOP_FIELD, STATIC_OOP_FIELD) +#undef START_CLASS +#undef END_CLASS +#undef FIELD +#undef CHAR_FIELD +#undef INT_FIELD +#undef BOOLEAN_FIELD +#undef LONG_FIELD +#undef OOP_FIELD +#undef STATIC_OOP_FIELD + + diff -r 2fb867285938 -r c23d45daff9b src/share/vm/graal/graalVMEntries.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalVMEntries.cpp Wed Jun 08 13:40:25 2011 +0200 @@ -0,0 +1,710 @@ +/* + * Copyright (c) 2011, 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. + */ + +#include "precompiled.hpp" +#include "c1x/c1x_VMEntries.hpp" +#include "c1x/c1x_Compiler.hpp" +#include "c1x/c1x_JavaAccess.hpp" +#include "c1x/c1x_CodeInstaller.hpp" +#include "c1x/c1x_VMExits.hpp" +#include "c1x/c1x_VmIds.hpp" +#include "c1/c1_Runtime1.hpp" +#include "memory/oopFactory.hpp" + +// public byte[] RiMethod_code(long vmId); +JNIEXPORT jbyteArray JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1code(JNIEnv *env, jobject, jlong vmId) { + TRACE_C1X_3("VMEntries::RiMethod_code"); + methodHandle method = VmIds::get(vmId); + int code_size = method->code_size(); + jbyteArray result = env->NewByteArray(code_size); + env->SetByteArrayRegion(result, 0, code_size, (const jbyte *) method->code_base()); + return result; +} + +// public int RiMethod_maxStackSize(long vmId); +JNIEXPORT jint JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1maxStackSize(JNIEnv *, jobject, jlong vmId) { + TRACE_C1X_3("VMEntries::RiMethod_maxStackSize"); + return VmIds::get(vmId)->max_stack(); +} + +// public int RiMethod_maxLocals(long vmId); +JNIEXPORT jint JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1maxLocals(JNIEnv *, jobject, jlong vmId) { + TRACE_C1X_3("VMEntries::RiMethod_maxLocals"); + return VmIds::get(vmId)->max_locals(); +} + +// public RiType RiMethod_holder(long vmId); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1holder(JNIEnv *, jobject, jlong vmId) { + TRACE_C1X_3("VMEntries::RiMethod_holder"); + VM_ENTRY_MARK + KlassHandle klass = VmIds::get(vmId)->method_holder(); + Handle name = VmIds::toString(klass->name(), CHECK_NULL); + oop holder = C1XCompiler::createHotSpotTypeResolved(klass, name, CHECK_NULL); + return JNIHandles::make_local(THREAD, holder); +} + +// public String RiMethod_signature(long vmId); +JNIEXPORT jstring JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1signature(JNIEnv *env, jobject, jlong vmId) { + TRACE_C1X_3("VMEntries::RiMethod_signature"); + VM_ENTRY_MARK + methodOop method = VmIds::get(vmId); + return VmIds::toString(method->signature(), THREAD); +} + +// public int RiMethod_accessFlags(long vmId); +JNIEXPORT jint JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1accessFlags(JNIEnv *, jobject, jlong vmId) { + TRACE_C1X_3("VMEntries::RiMethod_accessFlags"); + return VmIds::get(vmId)->access_flags().as_int(); +} + +// public RiExceptionHandler[] RiMethod_exceptionHandlers(long vmId); +JNIEXPORT jobjectArray JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1exceptionHandlers(JNIEnv *, jobject, jlong vmId) { + TRACE_C1X_3("VMEntries::RiMethod_exceptionHandlers"); + VM_ENTRY_MARK + methodHandle method = VmIds::get(vmId); + typeArrayHandle handlers = method->exception_table(); + int handler_count = handlers.is_null() ? 0 : handlers->length() / 4; + + instanceKlass::cast(HotSpotExceptionHandler::klass())->initialize(CHECK_NULL); + objArrayHandle array = oopFactory::new_objArray(SystemDictionary::RiExceptionHandler_klass(), handler_count, CHECK_NULL); + + for (int i = 0; i < handler_count; i++) { + // exception handlers are stored as four integers: start bci, end bci, handler bci, catch class constant pool index + int base = i * 4; + Handle entry = instanceKlass::cast(HotSpotExceptionHandler::klass())->allocate_instance(CHECK_NULL); + HotSpotExceptionHandler::set_startBci(entry, handlers->int_at(base + 0)); + HotSpotExceptionHandler::set_endBci(entry, handlers->int_at(base + 1)); + HotSpotExceptionHandler::set_handlerBci(entry, handlers->int_at(base + 2)); + int catch_class_index = handlers->int_at(base + 3); + HotSpotExceptionHandler::set_catchClassIndex(entry, catch_class_index); + + if (catch_class_index == 0) { + HotSpotExceptionHandler::set_catchClass(entry, NULL); + } else { + constantPoolOop cp = instanceKlass::cast(method->method_holder())->constants(); + ciInstanceKlass* loading_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(method->method_holder()); + bool is_accessible = false; + ciKlass *klass = CURRENT_ENV->get_klass_by_index(cp, catch_class_index, is_accessible, loading_klass); + oop catch_class = C1XCompiler::get_RiType(klass, method->method_holder(), CHECK_NULL); + + HotSpotExceptionHandler::set_catchClass(entry, catch_class); + } + array->obj_at_put(i, entry()); + } + + return (jobjectArray) JNIHandles::make_local(array()); +} + +// public boolean RiMethod_hasBalancedMonitors(long vmId); +JNIEXPORT jint JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1hasBalancedMonitors(JNIEnv *, jobject, jlong vmId) { + TRACE_C1X_3("VMEntries::RiMethod_hasBalancedMonitors"); + ciMethod* cimethod; + { + VM_ENTRY_MARK; + cimethod = (ciMethod*)CURRENT_ENV->get_object(VmIds::get(vmId)); + } + return cimethod->has_balanced_monitors(); +} + +// public boolean RiMethod_uniqueConcreteMethod(long vmId); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1uniqueConcreteMethod(JNIEnv *, jobject, jlong vmId) { + TRACE_C1X_3("VMEntries::RiMethod_uniqueConcreteMethod"); + VM_ENTRY_MARK; + ciMethod* cimethod = (ciMethod*)CURRENT_ENV->get_object(VmIds::get(vmId)); + if (cimethod->holder()->is_interface()) { + // Cannot trust interfaces. Because of: + // interface I { void foo(); } + // class A { public void foo() {} } + // class B extends A implements I { } + // class C extends B { public void foo() { } } + // class D extends B { } + // Would lead to identify C.foo() as the unique concrete method for I.foo() without seeing A.foo(). + return false; + } + klassOop klass = (klassOop)cimethod->holder()->get_oop(); + methodHandle method((methodOop)cimethod->get_oop()); + methodHandle unique_concrete; + { + ResourceMark rm; + MutexLocker locker(Compile_lock); + unique_concrete = methodHandle(Dependencies::find_unique_concrete_method(klass, method())); + } + if (unique_concrete.is_null()) { + return NULL; + } + + Handle name = VmIds::toString(unique_concrete->name(), CHECK_NULL); + oop method_resolved = VMExits::createRiMethodResolved(VmIds::add(unique_concrete()), name, CHECK_NULL); + return JNIHandles::make_local(THREAD, method_resolved); +} + +// public RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiSignature_1lookupType(JNIEnv *env, jobject, jstring jname, jobject accessingClass) { + TRACE_C1X_3("VMEntries::RiSignature_lookupType"); + VM_ENTRY_MARK; + + Symbol* nameSymbol = VmIds::toSymbol(jname); + Handle name = JNIHandles::resolve(jname); + + oop result; + if (nameSymbol == vmSymbols::int_signature()) { + result = VMExits::createRiTypePrimitive((int) T_INT, THREAD); + } else if (nameSymbol == vmSymbols::long_signature()) { + result = VMExits::createRiTypePrimitive((int) T_LONG, THREAD); + } else if (nameSymbol == vmSymbols::bool_signature()) { + result = VMExits::createRiTypePrimitive((int) T_BOOLEAN, THREAD); + } else if (nameSymbol == vmSymbols::char_signature()) { + result = VMExits::createRiTypePrimitive((int) T_CHAR, THREAD); + } else if (nameSymbol == vmSymbols::short_signature()) { + result = VMExits::createRiTypePrimitive((int) T_SHORT, THREAD); + } else if (nameSymbol == vmSymbols::byte_signature()) { + result = VMExits::createRiTypePrimitive((int) T_BYTE, THREAD); + } else if (nameSymbol == vmSymbols::double_signature()) { + result = VMExits::createRiTypePrimitive((int) T_DOUBLE, THREAD); + } else if (nameSymbol == vmSymbols::float_signature()) { + result = VMExits::createRiTypePrimitive((int) T_FLOAT, THREAD); + } else { + klassOop resolved_type = NULL; + // if the name isn't in the symbol table then the class isn't loaded anyway... + if (nameSymbol != NULL) { + Handle classloader; + Handle protectionDomain; + if (JNIHandles::resolve(accessingClass) != NULL) { + classloader = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(accessingClass))->klass_part()->class_loader(); + protectionDomain = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(accessingClass))->klass_part()->protection_domain(); + } + resolved_type = SystemDictionary::resolve_or_null(nameSymbol, classloader, protectionDomain, THREAD); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + resolved_type = NULL; + } + } + if (resolved_type != NULL) { + result = C1XCompiler::createHotSpotTypeResolved(resolved_type, name, CHECK_NULL); + } else { + result = VMExits::createRiTypeUnresolved(name, THREAD); + } + } + + return JNIHandles::make_local(THREAD, result); +} + +// public Object RiConstantPool_lookupConstant(long vmId, int cpi); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupConstant(JNIEnv *env, jobject, jlong vmId, jint index) { + TRACE_C1X_3("VMEntries::RiConstantPool_lookupConstant"); + VM_ENTRY_MARK; + + constantPoolOop cp = VmIds::get(vmId); + + oop result = NULL; + constantTag tag = cp->tag_at(index); + if (tag.is_int()) { + result = VMExits::createCiConstant(CiKind::Int(), cp->int_at(index), CHECK_0); + } else if (tag.is_long()) { + result = VMExits::createCiConstant(CiKind::Long(), cp->long_at(index), CHECK_0); + } else if (tag.is_float()) { + result = VMExits::createCiConstantFloat(cp->float_at(index), CHECK_0); + } else if (tag.is_double()) { + result = VMExits::createCiConstantDouble(cp->double_at(index), CHECK_0); + } else if (tag.is_string() || tag.is_unresolved_string()) { + oop string = NULL; + if (cp->is_pseudo_string_at(index)) { + string = cp->pseudo_string_at(index); + } else { + string = cp->string_at(index, THREAD); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + // TODO: Gracefully exit compilation. + fatal("out of memory during compilation!"); + return NULL; + } + } + result = VMExits::createCiConstantObject(string, CHECK_0); + } else if (tag.is_klass() || tag.is_unresolved_klass()) { + bool ignore; + ciInstanceKlass* accessor = (ciInstanceKlass*) ciEnv::current()->get_object(cp->pool_holder()); + ciKlass* klass = ciEnv::current()->get_klass_by_index(cp, index, ignore, accessor); + result = C1XCompiler::get_RiType(klass, cp->pool_holder(), CHECK_NULL); + } else if (tag.is_object()) { + oop obj = cp->object_at(index); + assert(obj->is_instance(), "must be an instance"); + result = VMExits::createCiConstantObject(obj, CHECK_NULL); + } else { + ShouldNotReachHere(); + } + + return JNIHandles::make_local(THREAD, result); +} + +// public RiMethod RiConstantPool_lookupMethod(long vmId, int cpi, byte byteCode); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupMethod(JNIEnv *env, jobject, jlong vmId, jint index, jbyte byteCode) { + TRACE_C1X_3("VMEntries::RiConstantPool_lookupMethod"); + VM_ENTRY_MARK; + + index = C1XCompiler::to_cp_index_u2(index); + constantPoolHandle cp = VmIds::get(vmId); + + Bytecodes::Code bc = (Bytecodes::Code) (((int) byteCode) & 0xFF); + ciInstanceKlass* loading_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(cp->pool_holder()); + ciMethod *cimethod = CURRENT_ENV->get_method_by_index(cp, index, bc, loading_klass); + if (cimethod->is_loaded()) { + methodOop method = (methodOop) cimethod->get_oop(); + Handle name = VmIds::toString(method->name(), CHECK_NULL); + return JNIHandles::make_local(THREAD, VMExits::createRiMethodResolved(VmIds::add(method), name, THREAD)); + } else { + Handle name = VmIds::toString(cimethod->name()->get_symbol(), CHECK_NULL); + Handle signature = VmIds::toString(cimethod->signature()->as_symbol()->get_symbol(), CHECK_NULL); + Handle holder = C1XCompiler::get_RiType(cimethod->holder(), cp->klass(), THREAD); + return JNIHandles::make_local(THREAD, VMExits::createRiMethodUnresolved(name, signature, holder, THREAD)); + } +} + +// public RiSignature RiConstantPool_lookupSignature(long vmId, int cpi); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupSignature(JNIEnv *env, jobject, jlong vmId, jint index) { + fatal("currently unsupported"); + return NULL; +} + +// public RiType RiConstantPool_lookupType(long vmId, int cpi); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupType(JNIEnv *env, jobject, jlong vmId, jint index) { + TRACE_C1X_3("VMEntries::RiConstantPool_lookupType"); + VM_ENTRY_MARK; + + constantPoolOop cp = VmIds::get(vmId); + + ciInstanceKlass* loading_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(cp->pool_holder()); + bool is_accessible = false; + ciKlass *klass = CURRENT_ENV->get_klass_by_index(cp, index, is_accessible, loading_klass); + return JNIHandles::make_local(THREAD, C1XCompiler::get_RiType(klass, cp->klass(), THREAD)); +} + +// public RiField RiConstantPool_lookupField(long vmId, int cpi); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupField(JNIEnv *env, jobject, jlong vmId, jint index, jbyte byteCode) { + TRACE_C1X_3("VMEntries::RiConstantPool_lookupField"); + VM_ENTRY_MARK; + + index = C1XCompiler::to_cp_index_u2(index); + constantPoolOop cp = VmIds::get(vmId); + + ciInstanceKlass* loading_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(cp->pool_holder()); + ciField *field = CURRENT_ENV->get_field_by_index(loading_klass, index); + + Bytecodes::Code code = (Bytecodes::Code)(((int) byteCode) & 0xFF); + Handle field_handle = C1XCompiler::get_RiField(field, loading_klass, cp->pool_holder(), code, THREAD); + bool is_constant = field->is_constant(); + if (is_constant && field->is_static()) { + ciConstant constant = field->constant_value(); + oop constant_object = NULL; + switch (constant.basic_type()) { + case T_OBJECT: + case T_ARRAY: + { + ciObject* obj = constant.as_object(); + if (obj->is_null_object()) { + constant_object = VMExits::createCiConstantObject(NULL, CHECK_0); + } else if (obj->can_be_constant()) { + constant_object = VMExits::createCiConstantObject(constant.as_object()->get_oop(), CHECK_0); + } + } + break; + case T_DOUBLE: + constant_object = VMExits::createCiConstantDouble(constant.as_double(), CHECK_0); + break; + case T_FLOAT: + constant_object = VMExits::createCiConstantFloat(constant.as_float(), CHECK_0); + break; + case T_LONG: + constant_object = VMExits::createCiConstant(CiKind::Long(), constant.as_long(), CHECK_0); + break; + case T_INT: + constant_object = VMExits::createCiConstant(CiKind::Int(), constant.as_int(), CHECK_0); + break; + case T_SHORT: + constant_object = VMExits::createCiConstant(CiKind::Short(), constant.as_int(), CHECK_0); + break; + case T_CHAR: + constant_object = VMExits::createCiConstant(CiKind::Char(), constant.as_int(), CHECK_0); + break; + case T_BYTE: + constant_object = VMExits::createCiConstant(CiKind::Byte(), constant.as_int(), CHECK_0); + break; + case T_BOOLEAN: + constant_object = VMExits::createCiConstant(CiKind::Boolean(), constant.as_int(), CHECK_0); + break; + default: + constant.print(); + fatal("Unhandled constant"); + } + if (constant_object != NULL) { + HotSpotField::set_constant(field_handle, constant_object); + } + } + return JNIHandles::make_local(THREAD, field_handle()); +} + +// public RiConstantPool RiType_constantPool(HotSpotTypeResolved klass); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_1constantPool(JNIEnv *, jobject, jobject klass) { + TRACE_C1X_3("VMEntries::RiType_constantPool"); + VM_ENTRY_MARK; + + assert(JNIHandles::resolve(klass) != NULL, ""); + constantPoolOop constantPool = ((instanceKlass*)java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))->klass_part())->constants(); + return JNIHandles::make_local(VMExits::createRiConstantPool(VmIds::add(constantPool), THREAD)); +} + +// public RiMethod RiType_resolveMethodImpl(HotSpotTypeResolved klass, String name, String signature); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_3resolveMethodImpl(JNIEnv *, jobject, jobject resolved_type, jstring name, jstring signature) { + TRACE_C1X_3("VMEntries::RiType_resolveMethodImpl"); + VM_ENTRY_MARK; + + assert(JNIHandles::resolve(resolved_type) != NULL, ""); + klassOop klass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(resolved_type)); + Symbol* name_symbol = VmIds::toSymbol(name); + Symbol* signature_symbol = VmIds::toSymbol(signature); + methodOop method = klass->klass_part()->lookup_method(name_symbol, signature_symbol); + if (method == NULL) { + if (TraceC1X >= 3) { + ResourceMark rm; + tty->print_cr("Could not resolve method %s %s on klass %s", name_symbol->as_C_string(), signature_symbol->as_C_string(), klass->klass_part()->name()->as_C_string()); + } + return NULL; + } + return JNIHandles::make_local(THREAD, VMExits::createRiMethodResolved(VmIds::add(method), Handle(JNIHandles::resolve(name)), THREAD)); +} + +// public boolean RiType_isSubtypeOf(HotSpotTypeResolved klass, RiType other); +JNIEXPORT jboolean JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_2isSubtypeOf(JNIEnv *, jobject, jobject klass, jobject jother) { + TRACE_C1X_3("VMEntries::RiType_isSubtypeOf"); + oop other = JNIHandles::resolve(jother); + assert(other->is_a(HotSpotTypeResolved::klass()), "resolved hotspot type expected"); + assert(JNIHandles::resolve(klass) != NULL, ""); + klassOop thisKlass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)); + klassOop otherKlass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(other)); + if (thisKlass->klass_part()->oop_is_instance_slow()) { + return instanceKlass::cast(thisKlass)->is_subtype_of(otherKlass); + } else if (thisKlass->klass_part()->oop_is_array()) { + return arrayKlass::cast(thisKlass)->is_subtype_of(otherKlass); + } else { + fatal("unexpected class type"); + return false; + } +} + +// public RiType RiType_componentType(HotSpotResolvedType klass); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_1componentType(JNIEnv *, jobject, jobject klass) { + TRACE_C1X_3("VMEntries::RiType_componentType"); + ciArrayKlass* array_klass; + { + VM_ENTRY_MARK; + assert(JNIHandles::resolve(klass) != NULL, ""); + array_klass = (ciArrayKlass *) CURRENT_ENV->get_object(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))); + } + ciType* element_type = array_klass->element_type(); + + VM_ENTRY_MARK; + assert(JNIHandles::resolve(klass) != NULL, ""); + return JNIHandles::make_local(C1XCompiler::get_RiType(element_type, java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)), THREAD)); +} + +// public RiType RiType_superType(HotSpotResolvedType klass); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_1superType(JNIEnv *, jobject, jobject klass) { + TRACE_C1X_3("VMEntries::RiType_superType"); + VM_ENTRY_MARK; + KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))); + ciInstanceKlass* k = NULL; + + if (klass_handle->oop_is_array()) { + k = (ciInstanceKlass *) CURRENT_ENV->get_object(SystemDictionary::Object_klass()); + } else { + guarantee(klass_handle->oop_is_instance(), "must be instance klass"); + k = (ciInstanceKlass *) CURRENT_ENV->get_object(klass_handle()); + k = k->super(); + } + + if (k != NULL) { + return JNIHandles::make_local(C1XCompiler::get_RiType(k, klass_handle, THREAD)); + } else { + return NULL; + } +} + +// public RiType RiType_uniqueConcreteSubtype(HotSpotResolvedType klass); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_1uniqueConcreteSubtype(JNIEnv *, jobject, jobject klass) { + TRACE_C1X_3("VMEntries::RiType_uniqueConcreteSubtype"); + Thread* THREAD = Thread::current(); + KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))); + ciInstanceKlass* k = NULL; + { + VM_ENTRY_MARK; + k = (ciInstanceKlass *) CURRENT_ENV->get_object(klass_handle()); + } + + if (k->is_abstract()) { + ciInstanceKlass* sub = k->unique_concrete_subklass(); + if (sub != NULL && sub->is_leaf_type()) { + VM_ENTRY_MARK; + return JNIHandles::make_local(C1XCompiler::get_RiType(sub, klass_handle, THREAD)); + } + } else if (k->is_leaf_type()) { + assert(!k->is_interface(), ""); + return klass; + } + + return NULL; +} + +// public RiType RiType_arrayOf(HotSpotTypeResolved klass); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiType_1arrayOf(JNIEnv *, jobject, jobject klass) { + TRACE_C1X_3("VMEntries::RiType_arrayOf"); + VM_ENTRY_MARK; + + KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))); + KlassHandle array = klass_handle->array_klass(THREAD); + Handle name = VmIds::toString(array->name(), CHECK_NULL); + return JNIHandles::make_local(THREAD, C1XCompiler::createHotSpotTypeResolved(array, name, THREAD)); +} + +// public RiType getPrimitiveArrayType(CiKind kind); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_getPrimitiveArrayType(JNIEnv *env, jobject, jobject kind) { + TRACE_C1X_3("VMEntries::VMEntries_getPrimitiveArrayType"); + VM_ENTRY_MARK; + BasicType type = C1XCompiler::kindToBasicType(CiKind::typeChar(kind)); + assert(type != T_OBJECT, "primitive type expecteds"); + ciKlass* klass = ciTypeArrayKlass::make(type); + return JNIHandles::make_local(THREAD, C1XCompiler::get_RiType(klass, KlassHandle(), THREAD)); +} + +// public RiType getType(Class javaClass); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_getType(JNIEnv *env, jobject, jobject javaClass) { + TRACE_C1X_3("VMEntries::VMEntries_getType"); + VM_ENTRY_MARK; + oop javaClassOop = JNIHandles::resolve(javaClass); + if (javaClassOop == NULL) { + fatal("argument to VMEntries.getType must not be NULL"); + return NULL; + } else if (java_lang_Class::is_primitive(javaClassOop)) { + BasicType basicType = java_lang_Class::primitive_type(javaClassOop); + return JNIHandles::make_local(THREAD, VMExits::createRiTypePrimitive((int) basicType, THREAD)); + } else { + KlassHandle klass = java_lang_Class::as_klassOop(javaClassOop); + Handle name = java_lang_String::create_from_symbol(klass->name(), CHECK_NULL); + + oop type = C1XCompiler::createHotSpotTypeResolved(klass, name, CHECK_NULL); + return JNIHandles::make_local(THREAD, type); + } +} + + +// helpers used to set fields in the HotSpotVMConfig object +jfieldID getFieldID(JNIEnv* env, jobject obj, const char* name, const char* sig) { + jfieldID id = env->GetFieldID(env->GetObjectClass(obj), name, sig); + if (id == NULL) { + TRACE_C1X_1("field not found: %s (%s)", name, sig); + fatal("field not found"); + } + return id; +} + +void set_boolean(JNIEnv* env, jobject obj, const char* name, bool value) { env->SetBooleanField(obj, getFieldID(env, obj, name, "Z"), value); } +void set_int(JNIEnv* env, jobject obj, const char* name, int value) { env->SetIntField(obj, getFieldID(env, obj, name, "I"), value); } +void set_long(JNIEnv* env, jobject obj, const char* name, jlong value) { env->SetLongField(obj, getFieldID(env, obj, name, "J"), value); } +void set_object(JNIEnv* env, jobject obj, const char* name, jobject value) { env->SetObjectField(obj, getFieldID(env, obj, name, "Ljava/lang/Object;"), value); } +void set_int_array(JNIEnv* env, jobject obj, const char* name, jarray value) { env->SetObjectField(obj, getFieldID(env, obj, name, "[I"), value); } + +jboolean get_boolean(JNIEnv* env, jobject obj, const char* name) { return env->GetBooleanField(obj, getFieldID(env, obj, name, "Z")); } +jint get_int(JNIEnv* env, jobject obj, const char* name) { return env->GetIntField(obj, getFieldID(env, obj, name, "I")); } +jlong get_long(JNIEnv* env, jobject obj, const char* name) { return env->GetLongField(obj, getFieldID(env, obj, name, "J")); } +jobject get_object(JNIEnv* env, jobject obj, const char* name) { return env->GetObjectField(obj, getFieldID(env, obj, name, "Ljava/lang/Object;")); } +jobject get_object(JNIEnv* env, jobject obj, const char* name, const char* sig) { return env->GetObjectField(obj, getFieldID(env, obj, name, sig)); } + + +BasicType basicTypes[] = { T_BOOLEAN, T_BYTE, T_SHORT, T_CHAR, T_INT, T_FLOAT, T_LONG, T_DOUBLE, T_OBJECT }; +int basicTypeCount = sizeof(basicTypes) / sizeof(BasicType); + +// public HotSpotVMConfig getConfiguration(); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_getConfiguration(JNIEnv *env, jobject) { + jclass klass = env->FindClass("com/oracle/max/graal/runtime/HotSpotVMConfig"); + assert(klass != NULL, "HotSpot vm config class not found"); + jobject config = env->AllocObject(klass); +#ifdef _WIN64 + set_boolean(env, config, "windowsOs", true); +#else + set_boolean(env, config, "windowsOs", false); +#endif + set_boolean(env, config, "verifyPointers", VerifyOops); + set_boolean(env, config, "useFastLocking", UseFastLocking); + set_boolean(env, config, "useFastNewObjectArray", UseFastNewObjectArray); + set_boolean(env, config, "useFastNewTypeArray", UseFastNewTypeArray); + set_int(env, config, "codeEntryAlignment", CodeEntryAlignment); + set_int(env, config, "vmPageSize", os::vm_page_size()); + set_int(env, config, "stackShadowPages", StackShadowPages); + set_int(env, config, "hubOffset", oopDesc::klass_offset_in_bytes()); + set_int(env, config, "arrayLengthOffset", arrayOopDesc::length_offset_in_bytes()); + set_int(env, config, "klassStateOffset", instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc)); + set_int(env, config, "klassStateFullyInitialized", (int)instanceKlass::fully_initialized); + set_int(env, config, "threadTlabTopOffset", in_bytes(JavaThread::tlab_top_offset())); + set_int(env, config, "threadTlabEndOffset", in_bytes(JavaThread::tlab_end_offset())); + set_int(env, config, "threadObjectOffset", in_bytes(JavaThread::threadObj_offset())); + set_int(env, config, "instanceHeaderPrototypeOffset", Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()); + set_int(env, config, "threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset())); + set_int(env, config, "threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset())); + set_int(env, config, "threadMultiNewArrayStorage", in_bytes(JavaThread::c1x_multinewarray_storage_offset())); + set_int(env, config, "classMirrorOffset", klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes()); + + set_long(env, config, "debugStub", VmIds::addStub((address)warning)); + set_long(env, config, "instanceofStub", VmIds::addStub(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); + set_long(env, config, "verifyPointerStub", VmIds::addStub(Runtime1::entry_for(Runtime1::c1x_verify_pointer_id))); + set_long(env, config, "newInstanceStub", VmIds::addStub(Runtime1::entry_for(Runtime1::fast_new_instance_init_check_id))); + set_long(env, config, "unresolvedNewInstanceStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_instance_id))); + set_long(env, config, "newTypeArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_type_array_id))); + set_long(env, config, "newObjectArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_object_array_id))); + set_long(env, config, "newMultiArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_multi_array_id))); + set_long(env, config, "loadKlassStub", VmIds::addStub(Runtime1::entry_for(Runtime1::load_klass_patching_id))); + set_long(env, config, "accessFieldStub", VmIds::addStub(Runtime1::entry_for(Runtime1::access_field_patching_id))); + set_long(env, config, "resolveStaticCallStub", VmIds::addStub(SharedRuntime::get_resolve_static_call_stub())); + set_long(env, config, "inlineCacheMissStub", VmIds::addStub(SharedRuntime::get_ic_miss_stub())); + set_long(env, config, "unwindExceptionStub", VmIds::addStub(Runtime1::entry_for(Runtime1::c1x_unwind_exception_call_id))); + set_long(env, config, "handleExceptionStub", VmIds::addStub(Runtime1::entry_for(Runtime1::handle_exception_nofpu_id))); + set_long(env, config, "handleDeoptStub", VmIds::addStub(SharedRuntime::deopt_blob()->unpack())); + set_long(env, config, "monitorEnterStub", VmIds::addStub(Runtime1::entry_for(Runtime1::monitorenter_id))); + set_long(env, config, "monitorExitStub", VmIds::addStub(Runtime1::entry_for(Runtime1::monitorexit_id))); + set_long(env, config, "fastMonitorEnterStub", VmIds::addStub(Runtime1::entry_for(Runtime1::c1x_monitorenter_id))); + set_long(env, config, "fastMonitorExitStub", VmIds::addStub(Runtime1::entry_for(Runtime1::c1x_monitorexit_id))); + set_long(env, config, "safepointPollingAddress", (jlong)(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()))); + + BarrierSet* bs = Universe::heap()->barrier_set(); + switch (bs->kind()) { + case BarrierSet::CardTableModRef: + case BarrierSet::CardTableExtension: { + jlong base = (jlong)((CardTableModRefBS*)bs)->byte_map_base; + assert(base != 0, "unexpected byte_map_base"); + set_long(env, config, "cardtableStartAddress", base); + set_int(env, config, "cardtableShift", CardTableModRefBS::card_shift); + break; + } + case BarrierSet::ModRef: + case BarrierSet::Other: + set_long(env, config, "cardtableStartAddress", 0); + set_int(env, config, "cardtableShift", 0); + // No post barriers + break; +#ifndef SERIALGC + case BarrierSet::G1SATBCT: + case BarrierSet::G1SATBCTLogging: +#endif // SERIALGC + default: + ShouldNotReachHere(); + } + + jintArray arrayOffsets = env->NewIntArray(basicTypeCount); + for (int i=0; iSetIntArrayRegion(arrayOffsets, i, 1, &offset); + } + set_int_array(env, config, "arrayOffsets", arrayOffsets); + set_int(env, config, "arrayClassElementOffset", objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc)); + return config; +} + +// public void installMethod(HotSpotTargetMethod targetMethod); +JNIEXPORT void JNICALL Java_com_oracle_graal_runtime_VMEntries_installMethod(JNIEnv *jniEnv, jobject, jobject targetMethod) { + VM_ENTRY_MARK; + CodeInstaller installer(JNIHandles::resolve(targetMethod)); +} + +// public HotSpotProxy installStub(HotSpotTargetMethod targetMethod, String name); +JNIEXPORT jlong JNICALL Java_com_oracle_graal_runtime_VMEntries_installStub(JNIEnv *jniEnv, jobject, jobject targetMethod) { + VM_ENTRY_MARK; + jlong id; + CodeInstaller installer(JNIHandles::resolve(targetMethod), id); + return id; +} + +// public void recordBailout(String reason); +JNIEXPORT void JNICALL Java_com_oracle_graal_runtime_VMEntries_recordBailout(JNIEnv *jniEnv, jobject, jobject message) { + if (C1XBailoutIsFatal) { + Handle msg = JNIHandles::resolve(message); + if (!msg.is_null()) { + java_lang_String::print(msg, tty); + } + vm_abort(false); + } +} + + + + +#define CC (char*) /*cast a literal from (const char*)*/ +#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) + +#define PROXY "J" +#define TYPE "Lcom/sun/cri/ri/RiType;" +#define RESOLVED_TYPE "Lcom/oracle/max/graal/runtime/HotSpotTypeResolved;" +#define METHOD "Lcom/sun/cri/ri/RiMethod;" +#define SIGNATURE "Lcom/sun/cri/ri/RiSignature;" +#define FIELD "Lcom/sun/cri/ri/RiField;" +#define CONSTANT_POOL "Lcom/sun/cri/ri/RiConstantPool;" +#define EXCEPTION_HANDLERS "[Lcom/sun/cri/ri/RiExceptionHandler;" +#define TARGET_METHOD "Lcom/oracle/max/graal/runtime/HotSpotTargetMethod;" +#define CONFIG "Lcom/oracle/max/graal/runtime/HotSpotVMConfig;" +#define HS_METHOD "Lcom/oracle/max/graal/runtime/HotSpotMethod;" +#define CI_CONSTANT "Lcom/sun/cri/ci/CiConstant;" +#define CI_KIND "Lcom/sun/cri/ci/CiKind;" +#define STRING "Ljava/lang/String;" +#define OBJECT "Ljava/lang/Object;" +#define CLASS "Ljava/lang/Class;" + +JNINativeMethod VMEntries_methods[] = { + {CC"RiMethod_code", CC"("PROXY")[B", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1code)}, + {CC"RiMethod_maxStackSize", CC"("PROXY")I", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1maxStackSize)}, + {CC"RiMethod_maxLocals", CC"("PROXY")I", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1maxLocals)}, + {CC"RiMethod_holder", CC"("PROXY")"TYPE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1holder)}, + {CC"RiMethod_signature", CC"("PROXY")"STRING, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1signature)}, + {CC"RiMethod_accessFlags", CC"("PROXY")I", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1accessFlags)}, + {CC"RiMethod_exceptionHandlers", CC"("PROXY")"EXCEPTION_HANDLERS, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1exceptionHandlers)}, + {CC"RiMethod_hasBalancedMonitors", CC"("PROXY")Z", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1hasBalancedMonitors)}, + {CC"RiMethod_uniqueConcreteMethod", CC"("PROXY")"METHOD, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1uniqueConcreteMethod)}, + {CC"RiSignature_lookupType", CC"("STRING RESOLVED_TYPE")"TYPE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiSignature_1lookupType)}, + {CC"RiConstantPool_lookupConstant", CC"("PROXY"I)"OBJECT, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupConstant)}, + {CC"RiConstantPool_lookupMethod", CC"("PROXY"IB)"METHOD, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupMethod)}, + {CC"RiConstantPool_lookupSignature", CC"("PROXY"I)"SIGNATURE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupSignature)}, + {CC"RiConstantPool_lookupType", CC"("PROXY"I)"TYPE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupType)}, + {CC"RiConstantPool_lookupField", CC"("PROXY"IB)"FIELD, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiConstantPool_1lookupField)}, + {CC"RiType_constantPool", CC"("RESOLVED_TYPE")"CONSTANT_POOL, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_1constantPool)}, + {CC"RiType_resolveMethodImpl", CC"("RESOLVED_TYPE STRING STRING")"METHOD, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_3resolveMethodImpl)}, + {CC"RiType_isSubtypeOf", CC"("RESOLVED_TYPE TYPE")Z", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_2isSubtypeOf)}, + {CC"RiType_componentType", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_1componentType)}, + {CC"RiType_uniqueConcreteSubtype", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_1uniqueConcreteSubtype)}, + {CC"RiType_superType", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_1superType)}, + {CC"RiType_arrayOf", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiType_1arrayOf)}, + {CC"getPrimitiveArrayType", CC"("CI_KIND")"TYPE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_getPrimitiveArrayType)}, + {CC"getType", CC"("CLASS")"TYPE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_getType)}, + {CC"getConfiguration", CC"()"CONFIG, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_getConfiguration)}, + {CC"installMethod", CC"("TARGET_METHOD")V", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_installMethod)}, + {CC"installStub", CC"("TARGET_METHOD")"PROXY, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_installStub)}, + {CC"recordBailout", CC"("STRING")V", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_recordBailout)} +}; + +int VMEntries_methods_count() { + return sizeof(VMEntries_methods) / sizeof(JNINativeMethod); +} diff -r 2fb867285938 -r c23d45daff9b src/share/vm/graal/graalVMEntries.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalVMEntries.hpp Wed Jun 08 13:40:25 2011 +0200 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2011, 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. + */ + +#include "prims/jni.h" + +extern JNINativeMethod VMEntries_methods[]; +int VMEntries_methods_count(); + +// nothing here - no need to define the jni method implementations in a header file + + diff -r 2fb867285938 -r c23d45daff9b src/share/vm/graal/graalVMExits.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalVMExits.cpp Wed Jun 08 13:40:25 2011 +0200 @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2011, 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. + */ + +#include "precompiled.hpp" +#include "c1x/c1x_VMExits.hpp" + +// this is a *global* handle +jobject VMExits::_compilerPermObject; +jobject VMExits::_vmExitsPermObject; +jobject VMExits::_vmExitsPermKlass; + +KlassHandle VMExits::vmExitsKlass() { + if (JNIHandles::resolve(_vmExitsPermKlass) == NULL) { + klassOop result = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_c1x_VMExits(), SystemDictionary::java_system_loader(), NULL, Thread::current()); + check_not_null(result, "Couldn't find class com.sun.hotspot.c1x.VMExits"); + _vmExitsPermKlass = JNIHandles::make_global(result); + } + return KlassHandle((klassOop)JNIHandles::resolve_non_null(_vmExitsPermKlass)); +} + +Handle VMExits::compilerInstance() { + if (JNIHandles::resolve(_compilerPermObject) == NULL) { + KlassHandle compilerImplKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_c1x_CompilerImpl(), SystemDictionary::java_system_loader(), NULL, Thread::current()); + check_not_null(compilerImplKlass(), "Couldn't find class com.sun.hotspot.c1x.CompilerImpl"); + + JavaValue result(T_OBJECT); + JavaCalls::call_static(&result, compilerImplKlass, vmSymbols::getInstance_name(), vmSymbols::getInstance_signature(), Thread::current()); + check_pending_exception("Couldn't get Compiler"); + _compilerPermObject = JNIHandles::make_global((oop) result.get_jobject()); + } + return Handle(JNIHandles::resolve_non_null(_compilerPermObject)); +} + +Handle VMExits::instance() { + if (JNIHandles::resolve(_vmExitsPermObject) == NULL) { + KlassHandle compilerKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_c1x_Compiler(), SystemDictionary::java_system_loader(), NULL, Thread::current()); + check_not_null(compilerKlass(), "Couldn't find class com.sun.hotspot.c1x.Compiler"); + + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.set_receiver(compilerInstance()); + JavaCalls::call_interface(&result, compilerKlass, vmSymbols::getVMExits_name(), vmSymbols::getVMExits_signature(), &args, Thread::current()); + check_pending_exception("Couldn't get VMExits"); + _vmExitsPermObject = JNIHandles::make_global((oop) result.get_jobject()); + } + return Handle(JNIHandles::resolve_non_null(_vmExitsPermObject)); +} + +void VMExits::initializeCompiler() { + KlassHandle compilerImplKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_c1x_CompilerImpl(), SystemDictionary::java_system_loader(), NULL, Thread::current()); + check_not_null(compilerImplKlass(), "Couldn't find class com.sun.hotspot.c1x.CompilerImpl"); + + JavaValue result(T_VOID); + JavaCalls::call_static(&result, compilerImplKlass, vmSymbols::initialize_name(), vmSymbols::void_method_signature(), Thread::current()); + check_pending_exception("Couldn't initialize compiler"); +} + +jboolean VMExits::setOption(Handle option) { + assert(!option.is_null(), ""); + KlassHandle compilerKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_c1x_HotSpotOptions(), SystemDictionary::java_system_loader(), NULL, Thread::current()); + check_not_null(compilerKlass(), "Couldn't find class com.sun.hotspot.c1x.HotSpotOptions"); + + Thread* THREAD = Thread::current(); + JavaValue result(T_BOOLEAN); + JavaCalls::call_static(&result, compilerKlass, vmSymbols::setOption_name(), vmSymbols::setOption_signature(), option, THREAD); + check_pending_exception("Error while calling setOption"); + return result.get_jboolean(); +} + +void VMExits::setDefaultOptions() { + KlassHandle compilerKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_c1x_HotSpotOptions(), SystemDictionary::java_system_loader(), NULL, Thread::current()); + check_not_null(compilerKlass(), "Couldn't find class com.sun.hotspot.c1x.HotSpotOptions"); + + Thread* THREAD = Thread::current(); + JavaValue result(T_VOID); + JavaCalls::call_static(&result, compilerKlass, vmSymbols::setDefaultOptions_name(), vmSymbols::void_method_signature(), THREAD); + check_pending_exception("Error while calling setDefaultOptions"); +} + +void VMExits::compileMethod(jlong methodVmId, Handle name, int entry_bci) { + assert(!name.is_null(), "just checking"); + Thread* THREAD = Thread::current(); + JavaValue result(T_VOID); + JavaCallArguments args; + args.push_oop(instance()); + args.push_long(methodVmId); + args.push_oop(name); + args.push_int(entry_bci); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::compileMethod_name(), vmSymbols::compileMethod_signature(), &args, THREAD); + check_pending_exception("Error while calling compileMethod"); +} + +oop VMExits::createRiMethodResolved(jlong vmId, Handle name, TRAPS) { + assert(!name.is_null(), "just checking"); + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_oop(instance()); + args.push_long(vmId); + args.push_oop(name); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiMethodResolved_name(), vmSymbols::createRiMethodResolved_signature(), &args, THREAD); + check_pending_exception("Error while calling createRiMethodResolved"); + return (oop) result.get_jobject(); +} + +oop VMExits::createRiMethodUnresolved(Handle name, Handle signature, Handle holder, TRAPS) { + assert(!name.is_null(), "just checking"); + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_oop(instance()); + args.push_oop(name); + args.push_oop(signature); + args.push_oop(holder); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiMethodUnresolved_name(), vmSymbols::createRiMethodUnresolved_signature(), &args, THREAD); + check_pending_exception("Error while calling createRiMethodUnresolved"); + return (oop) result.get_jobject(); +} + +oop VMExits::createRiField(Handle holder, Handle name, Handle type, int index, int flags, TRAPS) { + assert(!holder.is_null(), "just checking"); + assert(!name.is_null(), "just checking"); + assert(!type.is_null(), "just checking"); + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_oop(instance()); + args.push_oop(holder); + args.push_oop(name); + args.push_oop(type); + args.push_int(index); + args.push_int(flags); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiField_name(), vmSymbols::createRiField_signature(), &args, THREAD); + check_pending_exception("Error while calling createRiField"); + assert(result.get_type() == T_OBJECT, "just checking"); + return (oop) result.get_jobject(); +} + +oop VMExits::createRiType(jlong vmId, Handle name, TRAPS) { + assert(!name.is_null(), "just checking"); + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_oop(instance()); + args.push_long(vmId); + args.push_oop(name); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiType_name(), vmSymbols::createRiType_signature(), &args, THREAD); + check_pending_exception("Error while calling createRiType"); + return (oop) result.get_jobject(); +} + +oop VMExits::createRiTypePrimitive(int basic_type, TRAPS) { + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_oop(instance()); + args.push_int(basic_type); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiTypePrimitive_name(), vmSymbols::createRiTypePrimitive_signature(), &args, THREAD); + check_pending_exception("Error while calling createRiTypePrimitive"); + return (oop) result.get_jobject(); +} + +oop VMExits::createRiTypeUnresolved(Handle name, TRAPS) { + assert(!name.is_null(), "just checking"); + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_oop(instance()); + args.push_oop(name); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiTypeUnresolved_name(), vmSymbols::createRiTypeUnresolved_signature(), &args, THREAD); + check_pending_exception("Error while calling createRiTypeUnresolved"); + return (oop) result.get_jobject(); +} + +oop VMExits::createRiConstantPool(jlong vmId, TRAPS) { + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_oop(instance()); + args.push_long(vmId); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiConstantPool_name(), vmSymbols::createRiConstantPool_signature(), &args, THREAD); + check_pending_exception("Error while calling createRiConstantPool"); + return (oop) result.get_jobject(); +} + +oop VMExits::createRiSignature(Handle name, TRAPS) { + assert(!name.is_null(), "just checking"); + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_oop(instance()); + args.push_oop(name); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiSignature_name(), vmSymbols::createRiSignature_signature(), &args, THREAD); + check_pending_exception("Error while calling createRiSignature"); + return (oop) result.get_jobject(); +} + +oop VMExits::createCiConstant(Handle kind, jlong value, TRAPS) { + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_oop(instance()); + args.push_oop(kind()); + args.push_long(value); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createCiConstant_name(), vmSymbols::createCiConstant_signature(), &args, THREAD); + check_pending_exception("Error while calling createCiConstantFloat"); + return (oop) result.get_jobject(); + +} + +oop VMExits::createCiConstantFloat(jfloat value, TRAPS) { + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_oop(instance()); + args.push_float(value); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createCiConstantFloat_name(), vmSymbols::createCiConstantFloat_signature(), &args, THREAD); + check_pending_exception("Error while calling createCiConstantFloat"); + return (oop) result.get_jobject(); + +} + +oop VMExits::createCiConstantDouble(jdouble value, TRAPS) { + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_oop(instance()); + args.push_double(value); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createCiConstantDouble_name(), vmSymbols::createCiConstantDouble_signature(), &args, THREAD); + check_pending_exception("Error while calling createCiConstantDouble"); + return (oop) result.get_jobject(); +} + +oop VMExits::createCiConstantObject(Handle object, TRAPS) { + JavaValue result(T_OBJECT); + JavaCallArguments args; + /* + args.push_oop(instance()); + args.push_oop(object); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createCiConstantObject_name(), vmSymbols::createCiConstantObject_signature(), &args, THREAD); + check_pending_exception("Error while calling createCiConstantObject"); + */ + + + KlassHandle klass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_cri_ci_CiConstant(), SystemDictionary::java_system_loader(), NULL, Thread::current()); + JavaCalls::call_static(&result, klass(), vmSymbols::forObject_name(), vmSymbols::createCiConstantObject_signature(), object, THREAD); + check_pending_exception("Error while calling CiConstant.forObject"); + return (oop) result.get_jobject(); +} diff -r 2fb867285938 -r c23d45daff9b src/share/vm/graal/graalVMExits.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalVMExits.hpp Wed Jun 08 13:40:25 2011 +0200 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2011, 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. + */ + +#include "memory/allocation.hpp" +#include "oops/oop.hpp" +#include "runtime/handles.hpp" +#include "runtime/thread.hpp" +#include "classfile/javaClasses.hpp" +#include "runtime/jniHandles.hpp" +#include "runtime/javaCalls.hpp" + +class VMExits : public AllStatic { + +private: + static jobject _compilerPermObject; + static jobject _vmExitsPermObject; + static jobject _vmExitsPermKlass; + + static KlassHandle vmExitsKlass(); + static Handle instance(); + +public: + static void initializeCompiler(); + + static Handle compilerInstance(); + + // public static boolean HotSpotOptions.setOption(String option); + static jboolean setOption(Handle option); + + // public static void HotSpotOptions.setDefaultOptions(); + static void setDefaultOptions(); + + // public abstract void compileMethod(long vmId, String name, int entry_bci); + static void compileMethod(jlong vmId, Handle name, int entry_bci); + + // public abstract RiMethod createRiMethodResolved(long vmId, String name); + static oop createRiMethodResolved(jlong vmId, Handle name, TRAPS); + + // public abstract RiMethod createRiMethodUnresolved(String name, String signature, RiType holder); + static oop createRiMethodUnresolved(Handle name, Handle signature, Handle holder, TRAPS); + + // public abstract RiField createRiField(RiType holder, String name, RiType type, int flags, int offset); + static oop createRiField(Handle holder, Handle name, Handle type, int index, int flags, TRAPS); + + // public abstract RiType createRiType(long vmId, String name); + static oop createRiType(jlong vmId, Handle name, TRAPS); + + // public abstract RiType createRiTypeUnresolved(String name); + static oop createRiTypeUnresolved(Handle name, TRAPS); + + // public abstract RiConstantPool createRiConstantPool(long vmId); + static oop createRiConstantPool(jlong vmId, TRAPS); + + // public abstract RiType createRiTypePrimitive(int basicType); + static oop createRiTypePrimitive(int basicType, TRAPS); + + // public abstract RiSignature createRiSignature(String signature); + static oop createRiSignature(Handle name, TRAPS); + + // public abstract CiConstant createCiConstant(CiKind kind, long value); + static oop createCiConstant(Handle kind, jlong value, TRAPS); + + // public abstract CiConstant createCiConstantFloat(float value); + static oop createCiConstantFloat(jfloat value, TRAPS); + + // public abstract CiConstant createCiConstantDouble(double value); + static oop createCiConstantDouble(jdouble value, TRAPS); + + // public abstract CiConstant createCiConstantObject(long vmId); + static oop createCiConstantObject(Handle object, TRAPS); +}; + +inline void check_pending_exception(const char* message, bool dump_core = false) { + Thread* THREAD = Thread::current(); + if (THREAD->has_pending_exception()) { + Handle exception = PENDING_EXCEPTION; + CLEAR_PENDING_EXCEPTION; + tty->print_cr("%s", message); + java_lang_Throwable::print(exception, tty); + tty->cr(); + java_lang_Throwable::print_stack_trace(exception(), tty); + vm_abort(dump_core); + } +} + +inline void check_not_null(void* value, const char* message, bool dump_core = false) { + if (value == NULL) { + tty->print_cr("%s", message); + vm_abort(dump_core); + } +} diff -r 2fb867285938 -r c23d45daff9b src/share/vm/graal/graalVmIds.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalVmIds.cpp Wed Jun 08 13:40:25 2011 +0200 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2011, 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. + */ + +#include "precompiled.hpp" +#include "c1x/c1x_VmIds.hpp" +#include "ci/ciUtilities.hpp" + +// VmIds implementation + +GrowableArray
* VmIds::_stubs = NULL; +GrowableArray* VmIds::_localHandles = NULL; + + +void VmIds::initializeObjects() { + if (_stubs == NULL) { + assert(_localHandles == NULL, "inconsistent state"); + _stubs = new (ResourceObj::C_HEAP) GrowableArray
(64, true); + _localHandles = new (ResourceObj::C_HEAP) GrowableArray (64, true); + } + assert(_localHandles->length() == 0, "invalid state"); +} + +void VmIds::cleanupLocalObjects() { + for (int i = 0; i < _localHandles->length(); i++) { + JNIHandles::destroy_global(_localHandles->at(i)); + } + _localHandles->clear(); +} + +jlong VmIds::addStub(address stub) { + assert(!_stubs->contains(stub), "duplicate stub"); + return _stubs->append(stub) | STUB; +} + +jlong VmIds::add(Handle obj, jlong type) { + assert(!obj.is_null(), "cannot add NULL handle"); + int idx = -1; + for (int i = 0; i < _localHandles->length(); i++) + if (JNIHandles::resolve_non_null(_localHandles->at(i)) == obj()) { + idx = i; + break; + } + if (idx == -1) { + if (JavaThread::current()->thread_state() == _thread_in_vm) { + idx = _localHandles->append(JNIHandles::make_global(obj)); + } else { + VM_ENTRY_MARK; + idx = _localHandles->append(JNIHandles::make_global(obj)); + } + } + return idx | type; +} + +address VmIds::getStub(jlong id) { + assert((id & TYPE_MASK) == STUB, "wrong id type, STUB expected"); + assert((id & ~TYPE_MASK) >= 0 && (id & ~TYPE_MASK) < _stubs->length(), "STUB index out of bounds"); + return _stubs->at(id & ~TYPE_MASK); +} + +oop VmIds::getObject(jlong id) { + assert((id & TYPE_MASK) != STUB, "wrong id type"); + assert((id & ~TYPE_MASK) >= 0 && (id & ~TYPE_MASK) < _localHandles->length(), "index out of bounds"); + return JNIHandles::resolve_non_null(_localHandles->at(id & ~TYPE_MASK)); +} + diff -r 2fb867285938 -r c23d45daff9b src/share/vm/graal/graalVmIds.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalVmIds.hpp Wed Jun 08 13:40:25 2011 +0200 @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2011, 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. + */ + +#include "memory/allocation.hpp" +#include "utilities/growableArray.hpp" +#include "oops/oop.hpp" +#include "runtime/handles.hpp" +#include "runtime/thread.hpp" +#include "classfile/javaClasses.hpp" +#include "runtime/jniHandles.hpp" + +class VmIds : public AllStatic { + +private: + static GrowableArray
* _stubs; + static GrowableArray* _localHandles; + + static oop getObject(jlong id); + +public: + // these constants needs to have the same values as the one in HotSpotProxy.java + static const jlong STUB = 0x100000000000000LL; // address + static const jlong METHOD = 0x200000000000000LL; // methodOop + static const jlong CLASS = 0x300000000000000LL; // klassOop + static const jlong CONSTANT_POOL = 0x500000000000000LL; // constantPoolOop + static const jlong CONSTANT = 0x600000000000000LL; // oop + static const jlong TYPE_MASK = 0xf00000000000000LL; + static const jlong DUMMY_CONSTANT = 0x6ffffffffffffffLL; + + // Initializes the VmIds for a compilation, by creating the arrays + static void initializeObjects(); + // Cleans up after a compilation, by deallocating the arrays + static void cleanupLocalObjects(); + + // Adds a stub address, and returns the corresponding vmId (which is of type STUB) + static jlong addStub(address stub); + + // Adds an object, and returns the corresponding vmId (with the given type) + static jlong add(Handle obj, jlong type); + + // Adds an object, and returns the corresponding vmId (the type of which is determined by the template parameter) + template static jlong add(T obj); + + + // Returns the stub address with the given vmId + static address getStub(jlong id); + // Returns the stub address with the given vmId taken from a java.lang.Long + static address getStub(oop id); + + // Returns the object with the given id, the return type is defined by the template parameter (which must correspond to the actual type of the vmId) + template static T get(jlong id); + + + // Helper function to convert a symbol to a java.lang.String object + template static T toString(Symbol* symbol, TRAPS); + + // Helper function to convert a java.lang.String object to a symbol (this will return NULL if the symbol doesn't exist in the system) + static Symbol* toSymbol(jstring string); + + // Helper function to get the contents of a java.lang.Long + static jlong getBoxedLong(oop obj); +}; + + +template <> inline jlong VmIds::add(methodOop obj){ + assert(obj != NULL, "trying to add NULL"); + assert(obj->is_method(), "trying to add mistyped object"); + return add(Handle(obj), METHOD); +} +template <> inline jlong VmIds::add(klassOop obj) { + assert(obj != NULL, "trying to add NULL"); + assert(obj->is_klass(), "trying to add mistyped object"); + return add(Handle(obj), CLASS); +} +template <> inline jlong VmIds::add(constantPoolOop obj) { + assert(obj != NULL, "trying to add NULL"); + assert(obj->is_constantPool(), "trying to add mistyped object"); + return add(Handle(obj), CONSTANT_POOL); +} +template <> inline jlong VmIds::add(oop obj) { + assert(obj != NULL, "trying to add NULL"); + assert(obj->is_oop(), "trying to add mistyped object"); + return add(Handle(obj), CONSTANT); +} + + +template <> inline methodOop VmIds::get(jlong id){ + assert((id & TYPE_MASK) == METHOD, "METHOD expected"); + assert(getObject(id)->is_method(), "methodOop expected"); + return (methodOop)getObject(id); +} +template <> inline klassOop VmIds::get(jlong id) { + assert((id & TYPE_MASK) == CLASS, "CLASS expected"); + assert(getObject(id)->is_klass(), "klassOop expected"); + return (klassOop)getObject(id); +} +template <> inline constantPoolOop VmIds::get(jlong id) { + assert((id & TYPE_MASK) == CONSTANT_POOL, "CONSTANT_POOL expected"); + assert(getObject(id)->is_constantPool(), "constantPoolOop expected"); + return (constantPoolOop)getObject(id); +} +template <> inline oop VmIds::get(jlong id) { + assert((id & TYPE_MASK) == CONSTANT, "CONSTANT expected"); + assert(getObject(id)->is_oop(true), "oop expected"); + return (oop)getObject(id); +} + +inline address VmIds::getStub(oop obj) { + return getStub(getBoxedLong(obj)); +} + +template <> inline Handle VmIds::toString(Symbol* symbol, TRAPS) { + return java_lang_String::create_from_symbol(symbol, THREAD); +} +template <> inline oop VmIds::toString(Symbol* symbol, TRAPS) { + return toString(symbol, THREAD)(); +} +template <> inline jstring VmIds::toString(Symbol* symbol, TRAPS) { + return (jstring)JNIHandles::make_local(toString(symbol, THREAD)); +} +template <> inline jobject VmIds::toString(Symbol* symbol, TRAPS) { + return JNIHandles::make_local(toString(symbol, THREAD)); +} + +inline Symbol* VmIds::toSymbol(jstring string) { + return java_lang_String::as_symbol_or_null(JNIHandles::resolve(string)); +} + +inline jlong VmIds::getBoxedLong(oop obj) { + assert(obj->is_oop(true), "cannot unbox null or non-oop"); + return obj->long_field(java_lang_boxing_object::value_offset_in_bytes(T_LONG)); +}