blob: c50e3cfbfcea063783bbf71580894b0965ff9596 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_DOMAIN "notify"
#include "cxxlog.h"
#include "platform_lowlevel.h"
#include "open/types.h"
#include "lock_manager.h"
#include "environment.h"
#include "exceptions.h"
#include "jni_utils.h"
#include "native_utils.h"
#include "vm_arrays.h"
#include "thread_generic.h"
#include "jthread.h"
#include "thread_manager.h"
#include "object.h"
#include "object_generic.h"
#include "mon_enter_exit.h"
#include "port_atomic.h"
#include "jit_runtime_support_common.h"
#include "vm_process.h"
#include "interpreter.h"
#include "vm_log.h"
void set_hash_bits(ManagedObject *p_obj)
{
U_8 hb = (U_8) (((POINTER_SIZE_INT)p_obj >> 3) & HASH_MASK) ;
// lowest 3 bits are not random enough so get rid of them
if (hb == 0)
hb = (23 & HASH_MASK); // NO hash = zero allowed, thus hard map hb = 0 to a fixed prime number
// don't care if the cmpxchg fails -- just means someone else already set the hash
port_atomic_cas8(P_HASH_CONTENTION_BYTE(p_obj),hb, 0);
}
/* $$$ GMJ
long generic_hashcode(ManagedObject *obj) {
return (long) gc_get_hashcode(obj);
}
*/
jint default_hashcode(Managed_Object_Handle obj) {
ManagedObject *p_obj = (ManagedObject*) obj;
if (!p_obj) return 0L;
if ( *P_HASH_CONTENTION_BYTE(p_obj) & HASH_MASK)
return *P_HASH_CONTENTION_BYTE(p_obj) & HASH_MASK;
set_hash_bits(p_obj);
if ( *P_HASH_CONTENTION_BYTE(p_obj) & HASH_MASK)
return *P_HASH_CONTENTION_BYTE(p_obj) & HASH_MASK;
DIE(("All the possible cases are supposed to be covered before"));
return 0xff;
}
long generic_hashcode(ManagedObject * p_obj)
{
return (long) gc_get_hashcode0((Managed_Object_Handle) p_obj);
}
jint object_get_generic_hashcode(JNIEnv*, jobject jobj)
{
jint hash;
if (jobj != NULL) {
hash = generic_hashcode(((ObjectHandle)jobj)->object);
} else {
hash = 0;
}
return hash;
}
jobject object_clone(JNIEnv *jenv, jobject jobj)
{
ASSERT_RAISE_AREA;
ManagedObject *result;
assert(hythread_is_suspend_enabled());
if(!jobj) {
// Throw NullPointerException.
throw_exception_from_jni(jenv, "java/lang/NullPointerException", 0);
return NULL;
}
tmn_suspend_disable();
ObjectHandle h = (ObjectHandle) jobj;
VTable *vt = h->object->vt();
unsigned size;
if((vt->class_properties & CL_PROP_ARRAY_MASK) != 0)
{
// clone an array
I_32 length = get_vector_length((Vector_Handle) h->object);
size = vt->clss->calculate_array_size(length);
assert(size > 0);
result = (ManagedObject*)
vm_new_vector_using_vtable_and_thread_pointer(length,
vt->clss->get_allocation_handle(), vm_get_gc_thread_local());
}
else
{
// clone an object
Global_Env *global_env = VM_Global_State::loader_env;
if (!class_is_subtype_fast(h->object->vt(), global_env->java_lang_Cloneable_Class))
{
tmn_suspend_enable();
throw_exception_from_jni(jenv, "java/lang/CloneNotSupportedException", 0);
return NULL;
}
size = vt->allocated_size;
result = vt->clss->allocate_instance();
}
if (result == NULL) {
tmn_suspend_enable();
exn_raise_object(VM_Global_State::loader_env->java_lang_OutOfMemoryError);
return NULL;
}
if(gc_requires_barriers())
gc_heap_wrote_object(result);
// Gregory - Skip object header copying, it should be initialized
// by GC already, and copying may erase some information that GC
// wrote in it at allocation time
const size_t skip = ManagedObject::get_constant_header_size();
assert(skip <= size);
jbyte *dest = (jbyte *)result + skip;
jbyte *src = (jbyte *)h->object + skip;
memcpy(dest, src, size - skip);
ObjectHandle new_handle = oh_allocate_local_handle();
new_handle->object = result;
tmn_suspend_enable();
return (jobject) new_handle;
}