Mercurial > hg > graal-compiler
diff src/share/vm/runtime/sharedRuntime.cpp @ 18041:52b4284cb496
Merge with jdk8u20-b26
author | Gilles Duboscq <duboscq@ssw.jku.at> |
---|---|
date | Wed, 15 Oct 2014 16:02:50 +0200 |
parents | 4703a9442f3f 0bf37f737702 |
children | 810222d74f7c |
line wrap: on
line diff
--- a/src/share/vm/runtime/sharedRuntime.cpp Thu Oct 16 10:21:29 2014 +0200 +++ b/src/share/vm/runtime/sharedRuntime.cpp Wed Oct 15 16:02:50 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -82,6 +82,8 @@ #include "c1/c1_Runtime1.hpp" #endif +PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC + // Shared stub locations RuntimeStub* SharedRuntime::_wrong_method_blob; RuntimeStub* SharedRuntime::_wrong_method_abstract_blob; @@ -408,7 +410,7 @@ #endif -#if defined(__SOFTFP__) || defined(PPC) +#if defined(__SOFTFP__) || defined(PPC32) double SharedRuntime::dsqrt(double f) { return sqrt(f); } @@ -500,6 +502,13 @@ assert(!nm->is_native_method(), "no exception handler"); assert(nm->header_begin() != nm->exception_begin(), "no exception handler"); if (nm->is_deopt_pc(return_address)) { + // If we come here because of a stack overflow, the stack may be + // unguarded. Reguard the stack otherwise if we return to the + // deopt blob and the stack bang causes a stack overflow we + // crash. + bool guard_pages_enabled = thread->stack_yellow_zone_enabled(); + if (!guard_pages_enabled) guard_pages_enabled = thread->reguard_stack(); + assert(guard_pages_enabled, "stack banging in deopt blob may cause crash"); return SharedRuntime::deopt_blob()->unpack_with_exception(); } else { return nm->exception_begin(); @@ -812,10 +821,13 @@ // going to be unwound. Dispatch to a shared runtime stub // which will cause the StackOverflowError to be fabricated // and processed. - // For stack overflow in deoptimization blob, cleanup thread. - if (thread->deopt_mark() != NULL) { - Deoptimization::cleanup_deopt_info(thread, NULL); - } + // Stack overflow should never occur during deoptimization: + // the compiled method bangs the stack by as much as the + // interpreter would need in case of a deoptimization. The + // deoptimization blob and uncommon trap blob bang the stack + // in a debug VM to verify the correctness of the compiled + // method stack banging. + assert(thread->deopt_mark() == NULL, "no stack overflow from deopt blob/uncommon trap"); Events::log_exception(thread, "StackOverflowError at " INTPTR_FORMAT, pc); return StubRoutines::throw_StackOverflowError_entry(); } @@ -1019,14 +1031,13 @@ * it gets turned into a tail-call on sparc, which runs into dtrace bug * 6254741. Once that is fixed we can remove the dummy return value. */ -int SharedRuntime::dtrace_object_alloc(oopDesc* o) { - return dtrace_object_alloc_base(Thread::current(), o); +int SharedRuntime::dtrace_object_alloc(oopDesc* o, int size) { + return dtrace_object_alloc_base(Thread::current(), o, size); } -int SharedRuntime::dtrace_object_alloc_base(Thread* thread, oopDesc* o) { +int SharedRuntime::dtrace_object_alloc_base(Thread* thread, oopDesc* o, int size) { assert(DTraceAllocProbes, "wrong call"); Klass* klass = o->klass(); - int size = o->size(); Symbol* name = klass->name(); #ifndef USDT2 HS_DTRACE_PROBE4(hotspot, object__alloc, get_java_tid(thread), @@ -2465,7 +2476,7 @@ ResourceMark rm; NOT_PRODUCT(int insts_size); - AdapterBlob* B = NULL; + AdapterBlob* new_adapter = NULL; AdapterHandlerEntry* entry = NULL; AdapterFingerPrint* fingerprint = NULL; { @@ -2497,7 +2508,8 @@ #ifdef ASSERT AdapterHandlerEntry* shared_entry = NULL; - if (VerifyAdapterSharing && entry != NULL) { + // Start adapter sharing verification only after the VM is booted. + if (VerifyAdapterSharing && (entry != NULL)) { shared_entry = entry; entry = NULL; } @@ -2513,41 +2525,44 @@ // Make a C heap allocated version of the fingerprint to store in the adapter fingerprint = new AdapterFingerPrint(total_args_passed, sig_bt); + // StubRoutines::code2() is initialized after this function can be called. As a result, + // VerifyAdapterCalls and VerifyAdapterSharing can fail if we re-use code that generated + // prior to StubRoutines::code2() being set. Checks refer to checks generated in an I2C + // stub that ensure that an I2C stub is called from an interpreter frame. + bool contains_all_checks = StubRoutines::code2() != NULL; + // Create I2C & C2I handlers - BufferBlob* buf = buffer_blob(); // the temporary code buffer in CodeCache if (buf != NULL) { CodeBuffer buffer(buf); short buffer_locs[20]; buffer.insts()->initialize_shared_locs((relocInfo*)buffer_locs, sizeof(buffer_locs)/sizeof(relocInfo)); + MacroAssembler _masm(&buffer); - entry = SharedRuntime::generate_i2c2i_adapters(&_masm, total_args_passed, comp_args_on_stack, sig_bt, regs, fingerprint); - #ifdef ASSERT if (VerifyAdapterSharing) { if (shared_entry != NULL) { - assert(shared_entry->compare_code(buf->code_begin(), buffer.insts_size(), total_args_passed, sig_bt), - "code must match"); + assert(shared_entry->compare_code(buf->code_begin(), buffer.insts_size()), "code must match"); // Release the one just created and return the original _adapters->free_entry(entry); return shared_entry; } else { - entry->save_code(buf->code_begin(), buffer.insts_size(), total_args_passed, sig_bt); + entry->save_code(buf->code_begin(), buffer.insts_size()); } } #endif - B = AdapterBlob::create(&buffer); + new_adapter = AdapterBlob::create(&buffer); NOT_PRODUCT(insts_size = buffer.insts_size()); } - if (B == NULL) { + if (new_adapter == NULL) { // CodeCache is full, disable compilation // Ought to log this but compile log is only per compile thread // and we're some non descript Java thread. @@ -2555,7 +2570,7 @@ CompileBroker::handle_full_code_cache(); return NULL; // Out of CodeCache space } - entry->relocate(B->content_begin()); + entry->relocate(new_adapter->content_begin()); #ifndef PRODUCT // debugging suppport if (PrintAdapterHandlers || PrintStubCode) { @@ -2574,22 +2589,25 @@ } } #endif - - _adapters->add(entry); + // Add the entry only if the entry contains all required checks (see sharedRuntime_xxx.cpp) + // The checks are inserted only if -XX:+VerifyAdapterCalls is specified. + if (contains_all_checks || !VerifyAdapterCalls) { + _adapters->add(entry); + } } // Outside of the lock - if (B != NULL) { + if (new_adapter != NULL) { char blob_id[256]; jio_snprintf(blob_id, sizeof(blob_id), "%s(%s)@" PTR_FORMAT, - B->name(), + new_adapter->name(), fingerprint->as_string(), - B->content_begin()); - Forte::register_stub(blob_id, B->content_begin(), B->content_end()); + new_adapter->content_begin()); + Forte::register_stub(blob_id, new_adapter->content_begin(),new_adapter->content_end()); if (JvmtiExport::should_post_dynamic_code_generated()) { - JvmtiExport::post_dynamic_code_generated(blob_id, B->content_begin(), B->content_end()); + JvmtiExport::post_dynamic_code_generated(blob_id, new_adapter->content_begin(), new_adapter->content_end()); } } return entry; @@ -2621,7 +2639,6 @@ delete _fingerprint; #ifdef ASSERT if (_saved_code) FREE_C_HEAP_ARRAY(unsigned char, _saved_code, mtCode); - if (_saved_sig) FREE_C_HEAP_ARRAY(Basictype, _saved_sig, mtCode); #endif } @@ -2630,35 +2647,30 @@ // Capture the code before relocation so that it can be compared // against other versions. If the code is captured after relocation // then relative instructions won't be equivalent. -void AdapterHandlerEntry::save_code(unsigned char* buffer, int length, int total_args_passed, BasicType* sig_bt) { +void AdapterHandlerEntry::save_code(unsigned char* buffer, int length) { _saved_code = NEW_C_HEAP_ARRAY(unsigned char, length, mtCode); - _code_length = length; + _saved_code_length = length; memcpy(_saved_code, buffer, length); - _total_args_passed = total_args_passed; - _saved_sig = NEW_C_HEAP_ARRAY(BasicType, _total_args_passed, mtCode); - memcpy(_saved_sig, sig_bt, _total_args_passed * sizeof(BasicType)); } -bool AdapterHandlerEntry::compare_code(unsigned char* buffer, int length, int total_args_passed, BasicType* sig_bt) { - if (length != _code_length) { +bool AdapterHandlerEntry::compare_code(unsigned char* buffer, int length) { + if (length != _saved_code_length) { return false; } - for (int i = 0; i < length; i++) { - if (buffer[i] != _saved_code[i]) { - return false; - } - } - return true; + + return (memcmp(buffer, _saved_code, length) == 0) ? true : false; } #endif -// Create a native wrapper for this native method. The wrapper converts the -// java compiled calling convention to the native convention, handlizes -// arguments, and transitions to native. On return from the native we transition -// back to java blocking if a safepoint is in progress. -nmethod *AdapterHandlerLibrary::create_native_wrapper(methodHandle method, int compile_id) { +/** + * Create a native wrapper for this native method. The wrapper converts the + * Java-compiled calling convention to the native convention, handles + * arguments, and transitions to native. On return from the native we transition + * back to java blocking if a safepoint is in progress. + */ +void AdapterHandlerLibrary::create_native_wrapper(methodHandle method) { ResourceMark rm; nmethod* nm = NULL; @@ -2667,16 +2679,19 @@ method->has_native_function(), "must have something valid to call!"); { - // perform the work while holding the lock, but perform any printing outside the lock + // Perform the work while holding the lock, but perform any printing outside the lock MutexLocker mu(AdapterHandlerLibrary_lock); // See if somebody beat us to it nm = method->code(); - if (nm) { - return nm; + if (nm != NULL) { + return; } + const int compile_id = CompileBroker::assign_compile_id(method, CompileBroker::standard_entry_bci); + assert(compile_id > 0, "Must generate native wrapper"); + + ResourceMark rm; - BufferBlob* buf = buffer_blob(); // the temporary code buffer in CodeCache if (buf != NULL) { CodeBuffer buffer(buf); @@ -2708,16 +2723,14 @@ int comp_args_on_stack = SharedRuntime::java_calling_convention(sig_bt, regs, total_args_passed, is_outgoing); // Generate the compiled-to-native wrapper code - nm = SharedRuntime::generate_native_wrapper(&_masm, - method, - compile_id, - sig_bt, - regs, - ret_type); + nm = SharedRuntime::generate_native_wrapper(&_masm, method, compile_id, sig_bt, regs, ret_type); + + if (nm != NULL) { + method->set_code(method, nm); + } } - } - - // Must unlock before calling set_code + } // Unlock AdapterHandlerLibrary_lock + // Install the generated code. if (nm != NULL) { @@ -2725,13 +2738,11 @@ ttyLocker ttyl; CompileTask::print_compilation(tty, nm, method->is_static() ? "(static)" : ""); } - method->set_code(method, nm); nm->post_compiled_method_load_event(); } else { // CodeCache is full, disable compilation CompileBroker::handle_full_code_cache(); } - return nm; } JRT_ENTRY_NO_ASYNC(void, SharedRuntime::block_for_jni_critical(JavaThread* thread)) @@ -2749,19 +2760,20 @@ JRT_END #ifdef HAVE_DTRACE_H -// Create a dtrace nmethod for this method. The wrapper converts the -// java compiled calling convention to the native convention, makes a dummy call -// (actually nops for the size of the call instruction, which become a trap if -// probe is enabled). The returns to the caller. Since this all looks like a -// leaf no thread transition is needed. - +/** + * Create a dtrace nmethod for this method. The wrapper converts the + * Java-compiled calling convention to the native convention, makes a dummy call + * (actually nops for the size of the call instruction, which become a trap if + * probe is enabled), and finally returns to the caller. Since this all looks like a + * leaf, no thread transition is needed. + */ nmethod *AdapterHandlerLibrary::create_dtrace_nmethod(methodHandle method) { ResourceMark rm; nmethod* nm = NULL; if (PrintCompilation) { ttyLocker ttyl; - tty->print("--- n%s "); + tty->print("--- n "); method->print_short_name(tty); if (method->is_static()) { tty->print(" (static)"); @@ -2809,6 +2821,71 @@ } #endif // ndef HAVE_DTRACE_H +int SharedRuntime::convert_ints_to_longints_argcnt(int in_args_count, BasicType* in_sig_bt) { + int argcnt = in_args_count; + if (CCallingConventionRequiresIntsAsLongs) { + for (int in = 0; in < in_args_count; in++) { + BasicType bt = in_sig_bt[in]; + switch (bt) { + case T_BOOLEAN: + case T_CHAR: + case T_BYTE: + case T_SHORT: + case T_INT: + argcnt++; + break; + default: + break; + } + } + } else { + assert(0, "This should not be needed on this platform"); + } + + return argcnt; +} + +void SharedRuntime::convert_ints_to_longints(int i2l_argcnt, int& in_args_count, + BasicType*& in_sig_bt, VMRegPair*& in_regs) { + if (CCallingConventionRequiresIntsAsLongs) { + VMRegPair *new_in_regs = NEW_RESOURCE_ARRAY(VMRegPair, i2l_argcnt); + BasicType *new_in_sig_bt = NEW_RESOURCE_ARRAY(BasicType, i2l_argcnt); + + int argcnt = 0; + for (int in = 0; in < in_args_count; in++, argcnt++) { + BasicType bt = in_sig_bt[in]; + VMRegPair reg = in_regs[in]; + switch (bt) { + case T_BOOLEAN: + case T_CHAR: + case T_BYTE: + case T_SHORT: + case T_INT: + // Convert (bt) to (T_LONG,bt). + new_in_sig_bt[argcnt ] = T_LONG; + new_in_sig_bt[argcnt+1] = bt; + assert(reg.first()->is_valid() && !reg.second()->is_valid(), ""); + new_in_regs[argcnt ].set2(reg.first()); + new_in_regs[argcnt+1].set_bad(); + argcnt++; + break; + default: + // No conversion needed. + new_in_sig_bt[argcnt] = bt; + new_in_regs[argcnt] = reg; + break; + } + } + assert(argcnt == i2l_argcnt, "must match"); + + in_regs = new_in_regs; + in_sig_bt = new_in_sig_bt; + in_args_count = i2l_argcnt; + } else { + assert(0, "This should not be needed on this platform"); + } +} + // ------------------------------------------------------------------------- // Java-Java calling convention // (what you use when Java calls Java)